diff --git a/.github/workflows/action-test-before-PR.yml b/.github/workflows/action-test-before-PR.yml new file mode 100644 index 0000000..5750903 --- /dev/null +++ b/.github/workflows/action-test-before-PR.yml @@ -0,0 +1,34 @@ +name: Run SOMEF tests before PR + +on: + pull_request: + branches: + - main #should be this branch or master? + workflow_dispatch: +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: "3.11" + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org | python3 - + + - name: Install dependencies + run: poetry install + + - name: Download NLTK data + run: poetry run python -m nltk.downloader wordnet omw-1.4 punkt punkt_tab stopwords + + - name: Configure SOMEF + run: poetry run somef_core configure -a + + - name: Run pytest + run: poetry run pytest -v src/somef_core/test/ diff --git a/.gitignore b/.gitignore index 9523bbe..af8bdf7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,12 @@ build/* dist/* env*/* +somef_core_env/ .vscode/ .ipynb_checkpoints/ config.json __pycache__/ +**/__pycache__/ .DS_Store Lib/* Scripts/* @@ -13,7 +15,7 @@ Scripts/* *.ttl env_3.9/* src/somef_core/create_corpus_for_NER.py -src/somef.egg-info/* +src/somef_core.egg-info/* local_tests/* Dockerfile_old repos.txt diff --git a/CITATION.cff b/CITATION.cff index b806beb..2b0dd79 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,9 +1,16 @@ -title: "SOMEF: Software metadata extraction framework" -license: Apache-2.0 +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: 'SOMEF: Software metadata extraction framework' +message: >- + If you use this software, please cite both the article + from preferred-citation and the software itself. +type: software authors: - family-names: Garijo given-names: Daniel - orcid: "http://orcid.org/0000-0003-0454-7145" + orcid: 'https://orcid.org/0000-0003-0454-7145' - family-names: Mao given-names: Allen - family-names: Dharmala @@ -20,18 +27,16 @@ authors: given-names: Jenifer - family-names: Mendoza given-names: Juanje - -cff-version: 1.2.0 -message: "If you use this software, please cite both the article from preferred-citation and the software itself." +license: Apache-2.0 preferred-citation: authors: - family-names: Kelley given-names: Aidan - family-names: Garijo given-names: Daniel - title: "A Framework for Creating Knowledge Graphs of Scientific Software Metadata" + title: A Framework for Creating Knowledge Graphs of Scientific Software Metadata type: article - journal: "Quantitative Science Studies" - pages: "1-37" + journal: Quantitative Science Studies + pages: 1-37 year: 2021 doi: 10.1162/qss_a_00167 diff --git a/Dockerfile b/Dockerfile index a986e1f..2f23ee2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN curl -sSL https://install.python-poetry.org | python3 - RUN pip install poetry-plugin-shell -WORKDIR "/somef-core" +WORKDIR "/somef_core" RUN poetry install diff --git a/README.md b/README.md index 45c57b6..9bde117 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,15 @@ # Software Metadata Extraction Framework CORE (SOMEF-core) -TO DO: Add other badges. - -[![Documentation Status](https://readthedocs.org/projects/somef-core/badge/?version=latest)](https://somef-core.readthedocs.io/en/latest/?badge=latest) - +[![Documentation Status](https://readthedocs.org/projects/somef/badge/?version=latest)](https://somef.readthedocs.io/en/latest/?badge=latest) +[![Python](https://img.shields.io/pypi/pyversions/somef.svg?style=plastic)](https://badge.fury.io/py/somef) [![PyPI](https://badge.fury.io/py/somef.svg)](https://badge.fury.io/py/somef) [![DOI](https://zenodo.org/badge/190487675.svg)](https://zenodo.org/badge/latestdoi/190487675) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/KnowledgeCaptureAndDiscovery/somef/HEAD?filepath=notebook%2FSOMEF%20Usage%20Example.ipynb) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) logo A command line interface for automatically extracting relevant metadata from code repositories (readme, configuration files, documentation, etc.). -This repository is extracted from https://github.com/SciCodes/somef-core/issues +This repository is extracted from https://github.com/SciCodes/somef-core/ +**Demo:** See a [demo running somef as a service](https://somef.linkeddata.es), through the [SOMEF-Vider tool](https://github.com/SoftwareUnderstanding/SOMEF-Vider/). **Authors:** Daniel Garijo, Allen Mao, Miguel Ángel García Delgado, Haripriya Dharmala, Vedant Diwanji, Jiaying Wang, Aidan Kelley, Jenifer Tabita Ciuciu-Kiss, Luca Angheluta and Juanje Mendoza. @@ -19,6 +18,13 @@ This repository is extracted from https://github.com/SciCodes/somef-core/issues Given a readme file (or a GitHub/Gitlab repository) SOMEF will extract the following categories (if present), listed in alphabetical order: - **Acknowledgement**: Text acknowledging funding sources or contributors +- **Application domain**: The application domain of the repository. Current supported domains include: Astrophysics, Audio, Computer vision, Graphs, Natural language processing, Reinforcement learning, Semantc web, Sequential. Domains are not mutually exclusive. These domains have been extracted from [awesome lists](https://github.com/topics/awesome-list) and [Papers with code](https://paperswithcode.com/). Find more information in our [documentation](https://somef.readthedocs.io/en/latest/) +- **Authors**: Person(s) or organization(s) responsible for the project. We recognize the following properties: + - Name: name of the author (including last name) + - Given name: First name of an author + - Family name: Last name of an author + - Email: email of author + - URL: website or ORCID associated with the author - **Build file**: Build file(s) of the project. For example, files used to create a Docker image for the target software, package files, etc. - **Citation**: Preferred citation as the authors have stated in their readme file. SOMEF recognizes Bibtex, Citation File Format files and other means by which authors cite their papers (e.g., by in-text citation). We aim to recognize the following properties: - Title: Title of the publication @@ -43,7 +49,7 @@ Given a readme file (or a GitHub/Gitlab repository) SOMEF will extract the follo - **Forks url**: Links to forks made of the project - **Full name**: Name + owner (owner/name) - **Full title**: If the repository is a short name, we will attempt to extract the longer version of the repository name -- **Identifier**: Identifier associated with the software (if any), such as Digital Object Identifiers. DOIs associated with publications will also be detected. +- **Identifier**: Identifier associated with the software (if any), such as Digital Object Identifiers and Software Heritage identifiers (SWH). DOIs associated with publications will also be detected. - **Images**: Images used to illustrate the software component - **Installation instructions**: A set of instructions that indicate how to install a target repository - **Invocation**: Execution command(s) needed to run a scientific software component @@ -52,6 +58,7 @@ Given a readme file (or a GitHub/Gitlab repository) SOMEF will extract the follo - **License**: License and usage terms of a software component - **Logo**: Main logo used to represent the target software component - **Name**: Name identifying a software component +- **Ontologies**: URL and path to the ontology files present in the repository - **Owner**: Name and type of the user or organization in charge of the repository - **Package distribution**: Links to package sites like pypi in case the repository has a package available. - **Package files**: Links to package files used to wrap the project in a package. @@ -69,18 +76,23 @@ Given a readme file (or a GitHub/Gitlab repository) SOMEF will extract the follo - Link to the tarball zip and code of the release - **Repository status**: Repository status as it is described in [repostatus.org](https://www.repostatus.org/). - **Requirements**: Pre-requisites and dependencies needed to execute a software component +- **Run**: Running instructions of a software component. It may be wider than the `invocation` category, as it may include several steps and explanations. +- **Runtime platform**: specifies runtime platform or script interpreter dependencies required to run the project.. +- **Script files**: Bash script files contained in the repository - **Stargazers count**: Total number of stargazers of the project - **Support**: Guidelines and links of where to obtain support for a software component - **Support channels**: Help channels one can use to get support about the target software component +- **Type**: type of software (command line application, notebook, ontology, scientific workflow, etc.) - **Usage examples**: Assumptions and considerations recorded by the authors when executing a software component, or examples on how to use it +- **Workflows**: URL and path to the computational workflow files present in the repository We use different supervised classifiers, header analysis, regular expressions, the GitHub/Gitlab API to retrieve all these fields (more than one technique may be used for each field) and language specific metadata parsers (e.g., for package files). Each extraction records its provenance, with the confidence and technique used on each step. For more information check the [output format description](https://somef.readthedocs.io/en/latest/output/) ## Documentation -The documentation for somef-core is available at [https://somef-core.readthedocs.io/en/latest/](https://somef-core.readthedocs.io/en/latest/) +See full documentation for somef-core is available at [https://somef-core.readthedocs.io/en/latest/](https://somef-core.readthedocs.io/en/latest/) -## Cite SOMEF and SOMEF-core: +## Cite SOMEF-core: Journal publication (preferred): @@ -132,7 +144,7 @@ To run somef_core, please follow the next steps: Clone this GitHub repository ``` -git clone https://github.com/KnowledgeCaptureAndDiscovery/somef-core.git +git clone https://github.com/SciCodes/somef-core.git ``` We use [Poetry](https://python-poetry.org/) to ensure library compatibility. It can be installed as follows: @@ -145,32 +157,36 @@ This option is recommended over installing Poetry with pip install. Now Poetry will handle the installation of SOMEF-core and all its dependencies configured in the `toml` file. -To test the correct installation of poetry run: +To test the correct installation of poetry run (poetry version `> 2.0.0`): ``` poetry --version ``` -Install somef and all their dependencies. +Install somef-core and all their dependencies. ``` cd /somef_core poetry install ``` -Now we need to access our virtual environment, to do so you have to install the [poetry plugin shell](https://github.com/python-poetry/poetry-plugin-shell) and run the following command: +Now we need to access our virtual environment, to do so you can run the following command: +```bash +poetry env activate ``` -pip install poetry-plugin-shell -``` -After `shell` is set up, you can run the following comand to access the virtual environment -``` -poetry shell +If the environment is not active, paste the command shown when `poetry env activate` is run, typically something like the command below: + +```bash +source /path_to_env/ENV_NAME/bin/activate ``` -Test SOMEF installation + +To learn more about poetry environment management, visit their official documentation [here](https://python-poetry.org/docs/managing-environments/). + +Test the SOMEF-core installation run: ```bash -somef --help +somef_core --help ``` If everything goes fine, you should see: @@ -189,7 +205,31 @@ Commands: ## Installing through Docker -We are working on this section +We provide a Docker image with SOMEF already installed. To run through Docker, you may build the Dockerfile provided in the repository by running: + +```bash +docker build -t somef . +``` + +Or just use the Docker image already built in [DockerHub](https://hub.docker.com/r/kcapd/somef): + +```bash +docker pull kcapd/somef +``` + +Then, to run your image just type: + +```bash +docker run --rm -it kcapd/somef +``` + +And you will be ready to use SOMEF (see section below). If you want to have access to the results we recommend [mounting a volume](https://docs.docker.com/storage/volumes/). For example, the following command will mount the current directory as the `out` folder in the Docker image: + +```bash +docker run -it --rm -v $PWD/:/out kcapd/somef +``` + +If you move any files produced by somef into `/out`, then you will be able to see them in your current directory. ## Configure @@ -228,6 +268,9 @@ Options: -h, --help Show this message and exit. ``` +### Updating SOMEF + +If you update SOMEF to a newer version, we recommend you `configure` again the library (by running `somef configure`). The rationale is that different versions may rely on classifiers which may be stored in a different path. ## Usage @@ -239,6 +282,7 @@ Usage: somef_core describe [OPTIONS] Running the Command Line Interface Options: + -t, --threshold FLOAT Threshold to classify the text [required] Input: [mutually_exclusive, required] -r, --repo_url URL Github/Gitlab Repository URL -d, --doc_src PATH Path to the README file source @@ -250,6 +294,15 @@ Options: output will be in JSON -c, --codemeta_out PATH Path to an output codemeta file + -g, --graph_out PATH Path to the output Knowledge Graph export + file. If supplied, the output will be a + Knowledge Graph, in the format given in the + --format option chosen (turtle, json-ld) + + -f, --graph_format [turtle|json-ld] + If the --graph_out option is given, this is + the format that the graph will be stored in + -p, --pretty Pretty print the JSON output file so that it is easy to compare to another JSON output file. @@ -264,6 +317,11 @@ Options: will be stored at the desired path + -all, --requirements_all Export all detected requirements, including + text and libraries (default). + + -v, --requirements_v Export only requirements from structured + sources (pom.xml, requirements.txt, etc.) -h, --help Show this message and exit. ``` @@ -273,9 +331,29 @@ Options: The following command extracts all metadata available from [https://github.com/dgarijo/Widoco/](https://github.com/dgarijo/Widoco/). ```bash -somef_core describe -r https://github.com/dgarijo/Widoco/ -o test.json +somef_core describe -r https://github.com/dgarijo/Widoco/ -o test.json -t 0.8 ``` +Try SOMEF in Binder with our sample notebook: [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/KnowledgeCaptureAndDiscovery/somef/HEAD?filepath=notebook%2FSOMEF%20Usage%20Example.ipynb) + ## Contribute: If you want to contribute with a pull request, please do so by submitting it to the `dev` branch. + +## Next features: + +To see upcoming features, please have a look at our [open issues](https://github.com/SciCodes/somef-core/issues) and [milestones](https://github.com/SciCodes/somef-core/milestones) + +## Extending SOMEF categories: + +To run a classifier with an additional category or remove an existing one, a corresponding path entry in the config.json should be provided and the category type should be added/removed in the category variable in `cli.py`. + +## Metadata Support + +SOMEF supports the extraction and analysis of metadata in package files of several programming languages. Current support includes: `setup.py` and `pyproject.toml` for Python, `pom.xml` for Java, `.gemspec` for Ruby, `DESCRIPTION` for R, `bower.json` for JavaScript, HTML or CSS, `.cabal` for Haskell, `cargo.toml` for RUST, `composer` for PHP, `.juliaProject.toml` for Julia , `AUTHORS`, `codemeta.json`, `publiccode.yml`, `dockerfile` and `citation.cff` +This includes identifying dependencies, runtime requirements, and development tools specified in project configuration files. + +## Limitations + +SOMEF is designed to work primarily with repositories written in English. +Repositories in other languages may not be processed as effectively, and results could be incomplete or less accurate. diff --git a/docs/author 2.md b/docs/author 2.md new file mode 100644 index 0000000..fd00768 --- /dev/null +++ b/docs/author 2.md @@ -0,0 +1,113 @@ +The following metadata fields can be extracted from a AUTHORS file. +These fields are defined in the [Authors file specification](https://opensource.google/documentation/reference/releasing/authors/), and are mapped according to the [CodeMeta crosswalk for AUTHORS files](https://github.com/codemeta/codemeta/blob/master/crosswalks/codemeta-V2.csv). + +| Software metadata category | SOMEF metadata JSON path | AUTHORS metadata file field | +|-------------------------------|---------------------------------------------|------------------------------| +| authors - value | authors[i].result.value | *(1)* value | +| authors - name | authors[i].result.name | *(2)* name | +| authors - email | authors[i].result.email | *(3)* email | +| authors - given name | authors[i].result.given_name | *(4)* if type person | +| authors - last name | authors[i].result.last_name | *(5)* if type person | + +--- + +*(1)* +- Regex: line.strip() +- Example: `Jane Doe ` +- Result: `Jane Doe ` + +*(2)* +- line[:email_match.start()].strip() +- Example: `Jane Doe ` +- Result: `Jane Doe` + +*(3)* +- Regex: re.search(r'<([^>]+)>', line) +- Example: `Jane Doe ` +- Result: `jane.doe@example.org` + +*(4)* +- First part of name +- Example: `Jane Doe ` +- Result: `Jane` + +*(5)* +- Second part of name +- Example: `Jane Doe ` +- Result: `Doe` + +## Supported files of authors. + +The following filenames are recognized and processed automatically: + +* `AUTHORS` +* `AUTHORS.md` +* `AUTHORS.txt` + +These files are expected to be located at the root of the repository. Filenames are matched case-insensitively. + +## Purpose and Format + +These files typically contain a list of individuals and/or organizations that have contributed to the project. While there is no universal standard for formatting, a widely referenced convention is Google's guidance: + +🔗 [Google Open Source: Authors Files Protocol](https://opensource.google/documentation/reference/releasing/authors/) + +The content may be structured as: + +* Simple plain text, with one contributor per line. +* Markdown-formatted text (`.md` files). +* Lines including contributor names, emails (e.g., `Name `), and sometimes affiliations. + +### Examples of Valid Entries + +```text +Jane Doe +John Smith +Acme Corporation +Google Inc. +``` + +### Examples of NON Valid Entries + +```text +JetBrains <> +Microsoft +Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung +scrawl - Top contributor +Tom +``` +## What Is Read vs. Discarded + +When processing these files, the parser will: + +**Include** lines that: + +* Contain person names, optionally with emails (`Name `). +* Clearly refer to organizations (e.g., "Google LLC", "OpenAI Inc."). + +**Discard** lines that: + +* Are headers, decorative separators, or markdown formatting (`#`, `*`, `=`, etc.). +* Contain only URLs or links. +* Are single words with no email and no organizational keyword (e.g., `JetBrains <>`). +* Are markdown or structured noise (`---`, `{}`, etc.). +* Contain more than four words and are not recognized as organizations — to avoid capturing generic or descriptive sentences (e.g., This line not is an author). + +### Special Cases + +* Entries with only a first name and an email are accepted but must not assign an empty `last_name`. +* Lines starting with `-` or `*` are considered lists, but only parsed if the content matches expected author patterns. +* Blocks enclosed in `{}` are stripped before parsing. +* Any line matching known organization suffixes (`Inc.`, `LLC`, `Ltd.`, `Corporation`) is treated as an organization, even if no email is present. +* Some organization names (e.g., Open Source Initiative) may be mistakenly treated as person names if they do not contain a company designator or email. To improve detection, it is recommended to use names like Open Source Initiative Inc. +* In such cases, only the meaningful part (typically the name) is extracted before any descriptive annotations. +For example, the line: +Tom Smith (Tom) - Project leader 2010-2018 +Will be interpreted as: +{ + "type": "Person", + "name": "Tom Smith", + "value": "Tom Smith", + "given_name": "Tom", + "last_name": "Smith" +} diff --git a/docs/author.md b/docs/author.md new file mode 100644 index 0000000..fd00768 --- /dev/null +++ b/docs/author.md @@ -0,0 +1,113 @@ +The following metadata fields can be extracted from a AUTHORS file. +These fields are defined in the [Authors file specification](https://opensource.google/documentation/reference/releasing/authors/), and are mapped according to the [CodeMeta crosswalk for AUTHORS files](https://github.com/codemeta/codemeta/blob/master/crosswalks/codemeta-V2.csv). + +| Software metadata category | SOMEF metadata JSON path | AUTHORS metadata file field | +|-------------------------------|---------------------------------------------|------------------------------| +| authors - value | authors[i].result.value | *(1)* value | +| authors - name | authors[i].result.name | *(2)* name | +| authors - email | authors[i].result.email | *(3)* email | +| authors - given name | authors[i].result.given_name | *(4)* if type person | +| authors - last name | authors[i].result.last_name | *(5)* if type person | + +--- + +*(1)* +- Regex: line.strip() +- Example: `Jane Doe ` +- Result: `Jane Doe ` + +*(2)* +- line[:email_match.start()].strip() +- Example: `Jane Doe ` +- Result: `Jane Doe` + +*(3)* +- Regex: re.search(r'<([^>]+)>', line) +- Example: `Jane Doe ` +- Result: `jane.doe@example.org` + +*(4)* +- First part of name +- Example: `Jane Doe ` +- Result: `Jane` + +*(5)* +- Second part of name +- Example: `Jane Doe ` +- Result: `Doe` + +## Supported files of authors. + +The following filenames are recognized and processed automatically: + +* `AUTHORS` +* `AUTHORS.md` +* `AUTHORS.txt` + +These files are expected to be located at the root of the repository. Filenames are matched case-insensitively. + +## Purpose and Format + +These files typically contain a list of individuals and/or organizations that have contributed to the project. While there is no universal standard for formatting, a widely referenced convention is Google's guidance: + +🔗 [Google Open Source: Authors Files Protocol](https://opensource.google/documentation/reference/releasing/authors/) + +The content may be structured as: + +* Simple plain text, with one contributor per line. +* Markdown-formatted text (`.md` files). +* Lines including contributor names, emails (e.g., `Name `), and sometimes affiliations. + +### Examples of Valid Entries + +```text +Jane Doe +John Smith +Acme Corporation +Google Inc. +``` + +### Examples of NON Valid Entries + +```text +JetBrains <> +Microsoft +Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung +scrawl - Top contributor +Tom +``` +## What Is Read vs. Discarded + +When processing these files, the parser will: + +**Include** lines that: + +* Contain person names, optionally with emails (`Name `). +* Clearly refer to organizations (e.g., "Google LLC", "OpenAI Inc."). + +**Discard** lines that: + +* Are headers, decorative separators, or markdown formatting (`#`, `*`, `=`, etc.). +* Contain only URLs or links. +* Are single words with no email and no organizational keyword (e.g., `JetBrains <>`). +* Are markdown or structured noise (`---`, `{}`, etc.). +* Contain more than four words and are not recognized as organizations — to avoid capturing generic or descriptive sentences (e.g., This line not is an author). + +### Special Cases + +* Entries with only a first name and an email are accepted but must not assign an empty `last_name`. +* Lines starting with `-` or `*` are considered lists, but only parsed if the content matches expected author patterns. +* Blocks enclosed in `{}` are stripped before parsing. +* Any line matching known organization suffixes (`Inc.`, `LLC`, `Ltd.`, `Corporation`) is treated as an organization, even if no email is present. +* Some organization names (e.g., Open Source Initiative) may be mistakenly treated as person names if they do not contain a company designator or email. To improve detection, it is recommended to use names like Open Source Initiative Inc. +* In such cases, only the meaningful part (typically the name) is extracted before any descriptive annotations. +For example, the line: +Tom Smith (Tom) - Project leader 2010-2018 +Will be interpreted as: +{ + "type": "Person", + "name": "Tom Smith", + "value": "Tom Smith", + "given_name": "Tom", + "last_name": "Smith" +} diff --git a/docs/bower 2.md b/docs/bower 2.md new file mode 100644 index 0000000..8318067 --- /dev/null +++ b/docs/bower 2.md @@ -0,0 +1,39 @@ +The following metadata fields can be extracted from a bower.json file. +These fields are defined in the [Bower specification](https://github.com/bower/spec/blob/master/json.md), currently at version **4.0.0**, and are mapped according to the [CodeMeta crosswalk for bower.json](https://github.com/codemeta/codemeta/blob/master/crosswalks/NodeJS.csv). + +| Software metadata category | SOMEF metadata JSON path | BOWER.JSON metadata file field | +|-----------------------------|---------------------------------------|---------------------| +| authors | authors[i].result.value | authors[] | +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the bower.json file | +| homepage | homepage[i].result.value | homepage | +| license | license[i].result.value | license | +| name | name[i].result.value | name | +| keywords | keywords[i].result.value | keywords | +| requirements - value | requirements[i].result.value | "dependencies": {"paq":"version"} -> paq: version *(1)* | +| requirements - name | requirements[i].result.name | "dependencies": {"paq":"version"} -> paq | +| requirements - version | requirements[i].result.version | "dependencies": {"paq":"version"} -> version | +| requirements - dependency type | requirements[i].result.dependency_type | dependencies -> runtime , devDependencies -> dev | +| version | version[i].result.value | version | + + +--- + +*(1)* + +- Example: +``` + "dependencies": { + "jquery": "^3.1.1", + "bootstrap": "^3.3.7", + "moment": "^2.17.1", + "components-font-awesome": "^4.7.0", + "font-awesome": "^4.7.0", + "materialize": "^0.97.8" + } + ``` + First item results: + - Result value: "jquery: ^3.1.1" + - Result name": "jquery" + - Result version": "^3.1.1" + - Result dependency_type": "runtime" because it is "dependencies"s \ No newline at end of file diff --git a/docs/bower.md b/docs/bower.md new file mode 100644 index 0000000..8318067 --- /dev/null +++ b/docs/bower.md @@ -0,0 +1,39 @@ +The following metadata fields can be extracted from a bower.json file. +These fields are defined in the [Bower specification](https://github.com/bower/spec/blob/master/json.md), currently at version **4.0.0**, and are mapped according to the [CodeMeta crosswalk for bower.json](https://github.com/codemeta/codemeta/blob/master/crosswalks/NodeJS.csv). + +| Software metadata category | SOMEF metadata JSON path | BOWER.JSON metadata file field | +|-----------------------------|---------------------------------------|---------------------| +| authors | authors[i].result.value | authors[] | +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the bower.json file | +| homepage | homepage[i].result.value | homepage | +| license | license[i].result.value | license | +| name | name[i].result.value | name | +| keywords | keywords[i].result.value | keywords | +| requirements - value | requirements[i].result.value | "dependencies": {"paq":"version"} -> paq: version *(1)* | +| requirements - name | requirements[i].result.name | "dependencies": {"paq":"version"} -> paq | +| requirements - version | requirements[i].result.version | "dependencies": {"paq":"version"} -> version | +| requirements - dependency type | requirements[i].result.dependency_type | dependencies -> runtime , devDependencies -> dev | +| version | version[i].result.value | version | + + +--- + +*(1)* + +- Example: +``` + "dependencies": { + "jquery": "^3.1.1", + "bootstrap": "^3.3.7", + "moment": "^2.17.1", + "components-font-awesome": "^4.7.0", + "font-awesome": "^4.7.0", + "materialize": "^0.97.8" + } + ``` + First item results: + - Result value: "jquery: ^3.1.1" + - Result name": "jquery" + - Result version": "^3.1.1" + - Result dependency_type": "runtime" because it is "dependencies"s \ No newline at end of file diff --git a/docs/cabal 2.md b/docs/cabal 2.md new file mode 100644 index 0000000..d72be9f --- /dev/null +++ b/docs/cabal 2.md @@ -0,0 +1,61 @@ +The following metadata fields can be extracted from a cabal file. +These fields are defined in the [Cabal specification](https://cabal.readthedocs.io/en/3.10/cabal-package.html), currently at version **3.10** and are mapped according to the [Codemeta crosswalk for cabal](https://github.com/codemeta/codemeta/blob/master/crosswalks/Cabal.csv). + +| Software metadata category | SOMEF metadata JSON path | CABAL metadata file field | +|-------------------------------|---------------------------------------|-----------------------------------------| +| description | description[i].result.value | synopsis / description *(1)*| +| development_status | development_status[i].result.value | stability | +| has_package_file | has_package_file[i].result.value | URL of the filename.cabal file | +| homepage | homepage[i].result.value | homepage *(2)* | +| issue_tracker | issue_tracker[i].result.value | bug-reports | +| license | license[i].result.value | Regex license *(3)* | +| package_id | package_id[i].value | name *(4)* | +| requirements - value | requirements[i].result.value | *(5)* | +| requirements - name | requirements[i].result.name | library.build-depends name *(5.1)* | +| requirements - version | requirements[i].result.version | library.build-depends version *(5.2)* | +| requirements - development type | requirements[i].result.development_type | "runtime" | +| version | version[i].result.value | version *(6)* | + +--- + +*(1)* +- Regex: `r'description:\s*(.*?)(?=\n\S|\Z)' → group[1]` +- Example: `description: text description` +- Result: `text description` + +*(2)* +- Regex: `re.search(r'homepage:\s*(.*)' → group[1]` +- Example: `homepage: https://github.com/joshuaclayton/unused#readme` +- Result: `https://github.com/joshuaclayton/unused#readme` + +*(3)* +- Regex: `r'license:\s*(.*)' → group[1]` +- Example: `license: BSD-3-Clause` +- Result: `BSD-3-Clause` + +*(4)* +- Regex: `r'name:\s*(.*)' → group[1]` +- Example: `name: unused` +- Result: `unused` + +*(5)*, *(5.1)*, *(5.2)* + +- Regex 1: `r'library\s*\n(.*?)(?=\n\S|\Z)' → group[1]` --> first look into library +- Regex 2: `r'build-depends:\s*(.*?)(?=\n\s*(?:[A-Za-z0-9_-]+\s*:|if\s|\Z)) ' → group[1]` --> build-depends into library content +- Regex 3: `r'^([a-zA-Z0-9-_]+)\s*(.*?)$'` --> extract groups for name and version +- Example: +``` +library + build-depends: + Cabal-syntax ^>= 3.17, + array >= 0.4.0.1 && < 0.6 +``` +- Result value: `Cabal-syntax ^>= 3.17` +- Result name: `Cabal-syntax` +- Result version: `^>= 3.17` + +*(6)* +- Regex: `r'version:\s*(.*)' → group[1]` +- Example: `version: 0.10.0.0` +- Result: `0.10.0.0` + diff --git a/docs/cabal.md b/docs/cabal.md new file mode 100644 index 0000000..d72be9f --- /dev/null +++ b/docs/cabal.md @@ -0,0 +1,61 @@ +The following metadata fields can be extracted from a cabal file. +These fields are defined in the [Cabal specification](https://cabal.readthedocs.io/en/3.10/cabal-package.html), currently at version **3.10** and are mapped according to the [Codemeta crosswalk for cabal](https://github.com/codemeta/codemeta/blob/master/crosswalks/Cabal.csv). + +| Software metadata category | SOMEF metadata JSON path | CABAL metadata file field | +|-------------------------------|---------------------------------------|-----------------------------------------| +| description | description[i].result.value | synopsis / description *(1)*| +| development_status | development_status[i].result.value | stability | +| has_package_file | has_package_file[i].result.value | URL of the filename.cabal file | +| homepage | homepage[i].result.value | homepage *(2)* | +| issue_tracker | issue_tracker[i].result.value | bug-reports | +| license | license[i].result.value | Regex license *(3)* | +| package_id | package_id[i].value | name *(4)* | +| requirements - value | requirements[i].result.value | *(5)* | +| requirements - name | requirements[i].result.name | library.build-depends name *(5.1)* | +| requirements - version | requirements[i].result.version | library.build-depends version *(5.2)* | +| requirements - development type | requirements[i].result.development_type | "runtime" | +| version | version[i].result.value | version *(6)* | + +--- + +*(1)* +- Regex: `r'description:\s*(.*?)(?=\n\S|\Z)' → group[1]` +- Example: `description: text description` +- Result: `text description` + +*(2)* +- Regex: `re.search(r'homepage:\s*(.*)' → group[1]` +- Example: `homepage: https://github.com/joshuaclayton/unused#readme` +- Result: `https://github.com/joshuaclayton/unused#readme` + +*(3)* +- Regex: `r'license:\s*(.*)' → group[1]` +- Example: `license: BSD-3-Clause` +- Result: `BSD-3-Clause` + +*(4)* +- Regex: `r'name:\s*(.*)' → group[1]` +- Example: `name: unused` +- Result: `unused` + +*(5)*, *(5.1)*, *(5.2)* + +- Regex 1: `r'library\s*\n(.*?)(?=\n\S|\Z)' → group[1]` --> first look into library +- Regex 2: `r'build-depends:\s*(.*?)(?=\n\s*(?:[A-Za-z0-9_-]+\s*:|if\s|\Z)) ' → group[1]` --> build-depends into library content +- Regex 3: `r'^([a-zA-Z0-9-_]+)\s*(.*?)$'` --> extract groups for name and version +- Example: +``` +library + build-depends: + Cabal-syntax ^>= 3.17, + array >= 0.4.0.1 && < 0.6 +``` +- Result value: `Cabal-syntax ^>= 3.17` +- Result name: `Cabal-syntax` +- Result version: `^>= 3.17` + +*(6)* +- Regex: `r'version:\s*(.*)' → group[1]` +- Example: `version: 0.10.0.0` +- Result: `0.10.0.0` + diff --git a/docs/cargo 2.md b/docs/cargo 2.md new file mode 100644 index 0000000..f50fc83 --- /dev/null +++ b/docs/cargo 2.md @@ -0,0 +1,41 @@ +The following metadata fields can be extracted from a cargo.toml file. +These fields are defined in the [Cargo.toml specification](https://doc.rust-lang.org/cargo/reference/manifest.html), and are mapped according to the [CodeMeta crosswalk for cargo.toml](https://github.com/codemeta/codemeta/blob/master/crosswalks/Cargo.csv). + +| Software metadata category | SOMEF metadata JSON path | CARGO.TOML metadata file field | +|-------------------------------|--------------------------------------------|------------------------------| +| authors - value | authors[i].result.value | package.authors | +| authors - name | authors[i].result.name | package.authors *(1)* | +| authors - email | authors[i].result.email | package.authors *(2)* | +| code_repository | code_repository[i].result.value | package.repository | +| description | description[i].result.value | package.description | +| has_package_file | has_package_file[i].result.value | URL of the cargo.toml file | +| keywords | keywords[i].result.value | package.keywords | +| license - value | license[i].result.value | package.license | +| license - spdx id | license[i].result.spdx_id | package.license *(3)* | +| license - name | license[i].result.name | package.license *(4)* | +| package_id | package_id[i].result.value | package.name | +| requirements - value | requirements[i].result.value | target.dependencies or depencencies name = version | +| requirements - name | requirements[i].result.name | target.dependencies or depencencies name | +| requirements - version | requirements[i].result.version | target.dependencies or depencencies version | +| requirements - development type | requirements[i].result.development_type | target.dependencies or dependencies (version, git, path, other) | +| version - value | version[i].result.value | package.version | +| version - tag | version[i].result.tag | package.version | + +--- + +*(1)* +- Regex: `re.search(r'<([^>]+)>', author_str)`--> look in package.authors, them from init until email init. +- Example: `authors = ["rustdesk "]` +- Result: `rustdesk` + +*(2)* +- Regex: `re.search(r'<([^>]+)>', author_str)`--> look in package.authors +- Example: `authors = ["rustdesk "]` +- Result: `info@rustdesk.com` + +*(3)*, *(4)* +- Look for expressions in a local dictionary with all the reference and spdx_id +- Example: `license = "Apache-2.0"` +- Result spdx_id: `Apache-2.0` +- Result name: `Apache License 2.0` + diff --git a/docs/cargo.md b/docs/cargo.md new file mode 100644 index 0000000..f50fc83 --- /dev/null +++ b/docs/cargo.md @@ -0,0 +1,41 @@ +The following metadata fields can be extracted from a cargo.toml file. +These fields are defined in the [Cargo.toml specification](https://doc.rust-lang.org/cargo/reference/manifest.html), and are mapped according to the [CodeMeta crosswalk for cargo.toml](https://github.com/codemeta/codemeta/blob/master/crosswalks/Cargo.csv). + +| Software metadata category | SOMEF metadata JSON path | CARGO.TOML metadata file field | +|-------------------------------|--------------------------------------------|------------------------------| +| authors - value | authors[i].result.value | package.authors | +| authors - name | authors[i].result.name | package.authors *(1)* | +| authors - email | authors[i].result.email | package.authors *(2)* | +| code_repository | code_repository[i].result.value | package.repository | +| description | description[i].result.value | package.description | +| has_package_file | has_package_file[i].result.value | URL of the cargo.toml file | +| keywords | keywords[i].result.value | package.keywords | +| license - value | license[i].result.value | package.license | +| license - spdx id | license[i].result.spdx_id | package.license *(3)* | +| license - name | license[i].result.name | package.license *(4)* | +| package_id | package_id[i].result.value | package.name | +| requirements - value | requirements[i].result.value | target.dependencies or depencencies name = version | +| requirements - name | requirements[i].result.name | target.dependencies or depencencies name | +| requirements - version | requirements[i].result.version | target.dependencies or depencencies version | +| requirements - development type | requirements[i].result.development_type | target.dependencies or dependencies (version, git, path, other) | +| version - value | version[i].result.value | package.version | +| version - tag | version[i].result.tag | package.version | + +--- + +*(1)* +- Regex: `re.search(r'<([^>]+)>', author_str)`--> look in package.authors, them from init until email init. +- Example: `authors = ["rustdesk "]` +- Result: `rustdesk` + +*(2)* +- Regex: `re.search(r'<([^>]+)>', author_str)`--> look in package.authors +- Example: `authors = ["rustdesk "]` +- Result: `info@rustdesk.com` + +*(3)*, *(4)* +- Look for expressions in a local dictionary with all the reference and spdx_id +- Example: `license = "Apache-2.0"` +- Result spdx_id: `Apache-2.0` +- Result name: `Apache License 2.0` + diff --git a/docs/codemetajson 2.md b/docs/codemetajson 2.md new file mode 100644 index 0000000..6fb84c8 --- /dev/null +++ b/docs/codemetajson 2.md @@ -0,0 +1,46 @@ +The following metadata fields can be extracted from a codemeta.json file. +These fields are defined in the [Codemeta specification](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv), currently at version **3.0**, and are mapped according to the properties and classes defined in the CodeMeta vocabulary. + +| Software metadata category | SOMEF metadata JSON path | CODEMETA.JSON metadata file field | +|-------------------------------|------------------------------|--------------------------------------------| +| application_domain | application_domain[i].result.value | applicationCategory | +| authors - value | authors[i].result.value | author.name or author.givenName + author.familyName | +| authors - email | authors[i].result.email | author.email | +| authors - affiliation | authors[i].result.affiliation | author.affiliation | +| authors - identifier | authors[i].result.identifier | author.identifier or author.@id | +| citation - value | citation[i].result.value | referencePublication.name or referencePublication.title | +| citation - title | citation[i].result.title | referencePublication.name or referencePublication.title | +| citation - url | citation[i].result.url | referencePublication.url | +| citation - date published | citation[i].result.date_published | referencePublication.datePublished +| citation - doi | citation[i].result.doi | referencePublication.identifier | +| code_repository | code_repository[i].result.value | codeRepository | +| continuous_integration | continuous_integration[i].result.value | contIntegration | +| date_created | date_created[i].result.value | dateCreated | +| date_updated | date_updated[i].result.value | dateModified | +| date_published | date_published[i].result .value | datePublished | +| description | description[i].result.value | description | +| development_status | development_status[i].result.value | developmentStatus | +| download_url | download_url[i].result.value | downloadUrl | +| has_package_file | has_package_file[i].result.value | URL of the codemeta.json file | +| funding - funder | funding[i].result.funder | funding.funder or funding.funder.name | +| funding - funding | funding[i].result.funding | String.fundingIdentifier | +| identifier | identifier[i].result.value | identifier | +| issue_tracker | issue_tracker[i].result.value | issueTracker | +| keywords | keywords[i].result.value | keywords | +| license - value | license[i].result .value | license.name | +| license - url | license[i].result.url | license.url | +| license - spdx id | license[i].result.spdx_id | license.identifier if "spdx.org/licenses/ | +| license - identifier | license[i].result.identifier | license.identifier or https://spdx.org/licenses/{license} | +| name | name[i].result.value | name | +| programming_languages - value | programming_languages[i].result.value | programmingLanguage.name | +| programming_languages - name | programming_languages[i].result.name | programmingLanguage.name | +| programming_languages - version | programming_languages[i].result.version | programmingLanguage.version | +| programming_languages - url | programming_languages[i].result.url | programmingLanguage.url | +| readme_url | readme_url[i].result.value | readme | +| requirements - value | requirements[i].result.value | softwareRequirements or softwareRequirements.name == softwareRequirements.version | +| requirements - name | requirements[i].result.name | softwareRequirements or softwareRequirements.name or softwareRequirements.identifier | +| requirements - version | requirements[i].result.version | softwareRequirements or softwareRequirements.version | +| version | version[i].result.value | softwareVersion or version | + + + \ No newline at end of file diff --git a/docs/codemetajson.md b/docs/codemetajson.md new file mode 100644 index 0000000..6fb84c8 --- /dev/null +++ b/docs/codemetajson.md @@ -0,0 +1,46 @@ +The following metadata fields can be extracted from a codemeta.json file. +These fields are defined in the [Codemeta specification](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv), currently at version **3.0**, and are mapped according to the properties and classes defined in the CodeMeta vocabulary. + +| Software metadata category | SOMEF metadata JSON path | CODEMETA.JSON metadata file field | +|-------------------------------|------------------------------|--------------------------------------------| +| application_domain | application_domain[i].result.value | applicationCategory | +| authors - value | authors[i].result.value | author.name or author.givenName + author.familyName | +| authors - email | authors[i].result.email | author.email | +| authors - affiliation | authors[i].result.affiliation | author.affiliation | +| authors - identifier | authors[i].result.identifier | author.identifier or author.@id | +| citation - value | citation[i].result.value | referencePublication.name or referencePublication.title | +| citation - title | citation[i].result.title | referencePublication.name or referencePublication.title | +| citation - url | citation[i].result.url | referencePublication.url | +| citation - date published | citation[i].result.date_published | referencePublication.datePublished +| citation - doi | citation[i].result.doi | referencePublication.identifier | +| code_repository | code_repository[i].result.value | codeRepository | +| continuous_integration | continuous_integration[i].result.value | contIntegration | +| date_created | date_created[i].result.value | dateCreated | +| date_updated | date_updated[i].result.value | dateModified | +| date_published | date_published[i].result .value | datePublished | +| description | description[i].result.value | description | +| development_status | development_status[i].result.value | developmentStatus | +| download_url | download_url[i].result.value | downloadUrl | +| has_package_file | has_package_file[i].result.value | URL of the codemeta.json file | +| funding - funder | funding[i].result.funder | funding.funder or funding.funder.name | +| funding - funding | funding[i].result.funding | String.fundingIdentifier | +| identifier | identifier[i].result.value | identifier | +| issue_tracker | issue_tracker[i].result.value | issueTracker | +| keywords | keywords[i].result.value | keywords | +| license - value | license[i].result .value | license.name | +| license - url | license[i].result.url | license.url | +| license - spdx id | license[i].result.spdx_id | license.identifier if "spdx.org/licenses/ | +| license - identifier | license[i].result.identifier | license.identifier or https://spdx.org/licenses/{license} | +| name | name[i].result.value | name | +| programming_languages - value | programming_languages[i].result.value | programmingLanguage.name | +| programming_languages - name | programming_languages[i].result.name | programmingLanguage.name | +| programming_languages - version | programming_languages[i].result.version | programmingLanguage.version | +| programming_languages - url | programming_languages[i].result.url | programmingLanguage.url | +| readme_url | readme_url[i].result.value | readme | +| requirements - value | requirements[i].result.value | softwareRequirements or softwareRequirements.name == softwareRequirements.version | +| requirements - name | requirements[i].result.name | softwareRequirements or softwareRequirements.name or softwareRequirements.identifier | +| requirements - version | requirements[i].result.version | softwareRequirements or softwareRequirements.version | +| version | version[i].result.value | softwareVersion or version | + + + \ No newline at end of file diff --git a/docs/composer 2.md b/docs/composer 2.md new file mode 100644 index 0000000..a3ac6e6 --- /dev/null +++ b/docs/composer 2.md @@ -0,0 +1,25 @@ +The following metadata fields can be extracted from a composer.json file. +These fields are defined in the [Composer.json specification](https://getcomposer.org/doc/04-schema.md), currently at version **2.8.12**, and are mapped to CodeMeta properties following the internal mapping implemented in the parser, since no dedicated CodeMeta crosswalk for composer.json exists. + +| Software metadata category | SOMEF metadata JSON path | COMPOSER.JSON metadata file field | +|-------------------------------|-----------------------------------|-----------------------------------| +| authors - value | authors[i].result.value | authors.name | +| authors - name | authors[i].result.name | authors.name | +| authors - name | authors[i].result email | authors.email | +| authors - url | authors[i].result.url | authors.homepage | +| authors - role | authors[i].result.role | authors.role | +| code_repository | code_repository[i].result.value | repository or repository.url | +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the composer.json file | +| homepage | homepage[i].result.value | homepage | +| keywords | keywords[i].result.value | keywords | +| license - value | license[i].result.value | license | +| license - spdx id | license[i].result.spdx_id | license(name:value) -> license.value if spdx_id | +| license - name | license[i].result.name | license(name:value) -> license.name | +| package_id | package_id[i].result.value | name | +| requirements - value | requirements[i].result.value | require.name require.version or require-dev.name reire-dev.version | +| requirements - name | requirements[i].result.name | require.name or require-dev.name | +| requirements - version | requirements[i].result.version | require.version or require-dev.version | +| requirements - dependency type | requirements[i].result.dependency_type | require = runtime or require-dev = dev | +| version - value | version[i].result.value | version | +| version - tag | version[i].result.tag | version | diff --git a/docs/composer.md b/docs/composer.md new file mode 100644 index 0000000..a3ac6e6 --- /dev/null +++ b/docs/composer.md @@ -0,0 +1,25 @@ +The following metadata fields can be extracted from a composer.json file. +These fields are defined in the [Composer.json specification](https://getcomposer.org/doc/04-schema.md), currently at version **2.8.12**, and are mapped to CodeMeta properties following the internal mapping implemented in the parser, since no dedicated CodeMeta crosswalk for composer.json exists. + +| Software metadata category | SOMEF metadata JSON path | COMPOSER.JSON metadata file field | +|-------------------------------|-----------------------------------|-----------------------------------| +| authors - value | authors[i].result.value | authors.name | +| authors - name | authors[i].result.name | authors.name | +| authors - name | authors[i].result email | authors.email | +| authors - url | authors[i].result.url | authors.homepage | +| authors - role | authors[i].result.role | authors.role | +| code_repository | code_repository[i].result.value | repository or repository.url | +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the composer.json file | +| homepage | homepage[i].result.value | homepage | +| keywords | keywords[i].result.value | keywords | +| license - value | license[i].result.value | license | +| license - spdx id | license[i].result.spdx_id | license(name:value) -> license.value if spdx_id | +| license - name | license[i].result.name | license(name:value) -> license.name | +| package_id | package_id[i].result.value | name | +| requirements - value | requirements[i].result.value | require.name require.version or require-dev.name reire-dev.version | +| requirements - name | requirements[i].result.name | require.name or require-dev.name | +| requirements - version | requirements[i].result.version | require.version or require-dev.version | +| requirements - dependency type | requirements[i].result.dependency_type | require = runtime or require-dev = dev | +| version - value | version[i].result.value | version | +| version - tag | version[i].result.tag | version | diff --git a/docs/description 2.md b/docs/description 2.md new file mode 100644 index 0000000..87c5eb8 --- /dev/null +++ b/docs/description 2.md @@ -0,0 +1,86 @@ +The following metadata fields can be extracted from a DESCRIPTION file. +These fields are defined in the [DESCRIPTON specification](https://r-pkgs.org/description.html), and are mapped according to the [CodeMeta crosswalk for DESCRIPTION files based in R Package](https://github.com/codemeta/codemeta/blob/master/crosswalks/R%20Package%20Description.csv). + +| Software metadata category | SOMEF metadata JSON path | DESCRIPTION metadata file field | +|-------------------------------|---------------------------------|---------------------| +| authors | authors[i].result.value | Authors *(1)* | +| authors | authors[i].result.email | Authors *(2)* | +| code_repository | code_repository[i].result.value | URL *(3)* | +| description | description[i].result.value | Description *(3)* | +| has_package_file | has_package_file[i].result.value | URL of the DESCRIPTION file | +| homepage | homepage[i].result.value | URL *(3)* | +| issue_tracker | issue_tracker[i].result.value | BugReports *(5)* | +| license | license[i].result.value | License *(6)* | +| package_id | package_id[i].result.value | Package *(6)* | +| version | version[i].result.value | Version *(7)* | + +--- + +*(1)*, *(2)* , +- Regex 1: `r'Authors@R:\s*c\(([\s\S]*?)\)\s*$' → group[1]` +- Regex 2: `find in group[1] all persons and extract first name (or organition), last name and email` +- Example: +``` + Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = "aut", + comment = c(ORCID = "0000-0003-4757-117X")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")) + ) +``` + +- Result: +``` +{'result': {'value': 'Hadley Wickham', 'type': 'Agent', 'email': 'hadley@posit.co'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/DESCRIPTION'}, {'result': {'value': 'Winston Chang', 'type': 'Agent'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/DESCRIPTION'} +``` + +*(3)* +- Regex: `'URL:\s*([^\n]+(?:\n\s+[^\n]+)*)'` +- if github.com or gitlab.com --> code_repository +- if not --> homepage + +- Example: +``` +URL: https://ggplot2.tidyverse.org, + https://github.com/tidyverse/ggplot2 +``` + +- Result code_repository: `'result': {'value': 'https://github.com/tidyverse/tidyverse', 'type': 'Url'}` +- Result hompeage: `'result': {'value': 'https://tidyverse.tidyverse.org', 'type': 'Url'}}` + + +*(3)* +- Regex: `r'Description:\s*([^\n]+(?:\n\s+[^\n]+)*)', content)` +- Example: +```Description: A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +``` +- Result: +``` +A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +``` + +*(5)* +- Regex: `'BugReports:\s*([^\n]+)'` +- Example: `BugReports: https://github.com/tidyverse/ggplot2/issues` +- Result: `https://github.com/tidyverse/ggplot2/issues` + +*(5)* +- Regex: `r'License:\s*([^\n]+)'`` +- Example: `License: MIT + file LICENSE` +- Result: `MIT + file LICENSE` + +*(6)* +- Regex: `r'Package:\s*([^\n]+)` +- Example: `Package: ggplot2` +- Result: `ggplot2` + +*(6)* +- Regex: `r'Version:\s*([^\n]+)'` +- Example: `Version: 2.0.0.9000` +- Result: `2.0.0.9000` diff --git a/docs/description.md b/docs/description.md new file mode 100644 index 0000000..87c5eb8 --- /dev/null +++ b/docs/description.md @@ -0,0 +1,86 @@ +The following metadata fields can be extracted from a DESCRIPTION file. +These fields are defined in the [DESCRIPTON specification](https://r-pkgs.org/description.html), and are mapped according to the [CodeMeta crosswalk for DESCRIPTION files based in R Package](https://github.com/codemeta/codemeta/blob/master/crosswalks/R%20Package%20Description.csv). + +| Software metadata category | SOMEF metadata JSON path | DESCRIPTION metadata file field | +|-------------------------------|---------------------------------|---------------------| +| authors | authors[i].result.value | Authors *(1)* | +| authors | authors[i].result.email | Authors *(2)* | +| code_repository | code_repository[i].result.value | URL *(3)* | +| description | description[i].result.value | Description *(3)* | +| has_package_file | has_package_file[i].result.value | URL of the DESCRIPTION file | +| homepage | homepage[i].result.value | URL *(3)* | +| issue_tracker | issue_tracker[i].result.value | BugReports *(5)* | +| license | license[i].result.value | License *(6)* | +| package_id | package_id[i].result.value | Package *(6)* | +| version | version[i].result.value | Version *(7)* | + +--- + +*(1)*, *(2)* , +- Regex 1: `r'Authors@R:\s*c\(([\s\S]*?)\)\s*$' → group[1]` +- Regex 2: `find in group[1] all persons and extract first name (or organition), last name and email` +- Example: +``` + Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = "aut", + comment = c(ORCID = "0000-0003-4757-117X")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")) + ) +``` + +- Result: +``` +{'result': {'value': 'Hadley Wickham', 'type': 'Agent', 'email': 'hadley@posit.co'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/DESCRIPTION'}, {'result': {'value': 'Winston Chang', 'type': 'Agent'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/DESCRIPTION'} +``` + +*(3)* +- Regex: `'URL:\s*([^\n]+(?:\n\s+[^\n]+)*)'` +- if github.com or gitlab.com --> code_repository +- if not --> homepage + +- Example: +``` +URL: https://ggplot2.tidyverse.org, + https://github.com/tidyverse/ggplot2 +``` + +- Result code_repository: `'result': {'value': 'https://github.com/tidyverse/tidyverse', 'type': 'Url'}` +- Result hompeage: `'result': {'value': 'https://tidyverse.tidyverse.org', 'type': 'Url'}}` + + +*(3)* +- Regex: `r'Description:\s*([^\n]+(?:\n\s+[^\n]+)*)', content)` +- Example: +```Description: A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +``` +- Result: +``` +A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +``` + +*(5)* +- Regex: `'BugReports:\s*([^\n]+)'` +- Example: `BugReports: https://github.com/tidyverse/ggplot2/issues` +- Result: `https://github.com/tidyverse/ggplot2/issues` + +*(5)* +- Regex: `r'License:\s*([^\n]+)'`` +- Example: `License: MIT + file LICENSE` +- Result: `MIT + file LICENSE` + +*(6)* +- Regex: `r'Package:\s*([^\n]+)` +- Example: `Package: ggplot2` +- Result: `ggplot2` + +*(6)* +- Regex: `r'Version:\s*([^\n]+)'` +- Example: `Version: 2.0.0.9000` +- Result: `2.0.0.9000` diff --git a/docs/dockerfiledoc 2.md b/docs/dockerfiledoc 2.md new file mode 100644 index 0000000..6dc668f --- /dev/null +++ b/docs/dockerfiledoc 2.md @@ -0,0 +1,30 @@ +The following metadata fields can be extracted from a Dockerfile. +These fields are defined using Dockerfile `LABEL` instructions as described in the +[Dockerfile reference](https://docs.docker.com/reference/dockerfile/) and are interpreted +according to the OCI Image Specification, following the +[mapping for OCI image annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys). + +| Software metadata category | SOMEF metadata JSON path | DOCKERFILE metadata file field | +|-----------------------------|-----------------------------------------|------------------------------------| +| authors | authors[i].result.value | org.opencontainers.image.authors *(1)* | +| authors | authors[i].result.value | LABEL maintainer *(1)* | +| code_repository | code_repository[i].result.value | org.opencontainers.image.url | +| description | description[i].result.value | org.opencontainers.image.description | +| documentation | documentation[i].result.value | org.opencontainers.image.documentation | +| license | license[i].result.value | org.opencontainers.image.licenses | +| name | name[i].result.value | org.opencontainers.image.ref.name | +| owner | owner[i].result.value | org.opencontainers.image.vendor | +| version | version[i].result.value | org.opencontainers.image.version | + + +--- + + +*(1)* +- Example: +``` +LABEL maintainer="The Prometheus Authors " +LABEL org.opencontainers.image.authors="The Prometheus Authors" \ +``` + + diff --git a/docs/dockerfiledoc.md b/docs/dockerfiledoc.md new file mode 100644 index 0000000..6dc668f --- /dev/null +++ b/docs/dockerfiledoc.md @@ -0,0 +1,30 @@ +The following metadata fields can be extracted from a Dockerfile. +These fields are defined using Dockerfile `LABEL` instructions as described in the +[Dockerfile reference](https://docs.docker.com/reference/dockerfile/) and are interpreted +according to the OCI Image Specification, following the +[mapping for OCI image annotations](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys). + +| Software metadata category | SOMEF metadata JSON path | DOCKERFILE metadata file field | +|-----------------------------|-----------------------------------------|------------------------------------| +| authors | authors[i].result.value | org.opencontainers.image.authors *(1)* | +| authors | authors[i].result.value | LABEL maintainer *(1)* | +| code_repository | code_repository[i].result.value | org.opencontainers.image.url | +| description | description[i].result.value | org.opencontainers.image.description | +| documentation | documentation[i].result.value | org.opencontainers.image.documentation | +| license | license[i].result.value | org.opencontainers.image.licenses | +| name | name[i].result.value | org.opencontainers.image.ref.name | +| owner | owner[i].result.value | org.opencontainers.image.vendor | +| version | version[i].result.value | org.opencontainers.image.version | + + +--- + + +*(1)* +- Example: +``` +LABEL maintainer="The Prometheus Authors " +LABEL org.opencontainers.image.authors="The Prometheus Authors" \ +``` + + diff --git a/docs/gemspec 2.md b/docs/gemspec 2.md new file mode 100644 index 0000000..b55cbd0 --- /dev/null +++ b/docs/gemspec 2.md @@ -0,0 +1,86 @@ +The following metadata fields can be extracted from a gemspec file. +These fields are defined in the [Ruby Gems specification](https://guides.rubygems.org/specification-reference/) currently at version **2.0**, and are mapped according to the [CodeMeta crosswalk for ruby gems](https://github.com/codemeta/codemeta/blob/master/crosswalks/Ruby%20Gem.csv). + +| Software metadata category | SOMEF metadata JSON path | .gemspec metadata file field | +|-------------------------------|--------------------------------|--------------------------------------| +| authors | authors[i].result.value | gem.authors *(1)* | +| description | description[i].resultvalue | description *(2)* | +| has_package_file | has_package_file[i].result.value | URL of the filename.gemspec file | +| homepage | homepage[i].result.value | homepage *(3)* | +| license - value | license[i].result.value | license/licenses *(4)* | +| license - spdx id | license[i].result.spdx_id | license/licenses *(4)* spdx_id | +| license - name | license[i].result.name | llicense/licenses name *(4)* | +| package_id | package_id[i].result.value | name *(5)* | +| requirements - value | requirements[i].result.value | requirements/add_dependency/add_development_dependency name:version *(6)* | +| requirements - name | requirements[i].result.name | requirements/add_dependency/add_development_dependency name *(6)* | +| requirements - version | requirements[i].result.version | requirements/add_dependency/add_development_dependency version *(6)* | +| requirements - development type | requirements[i].result.development_type | add_dependency -> runtime *(6)* | +| requirements - development type | requirements[i].result.development_type | add_development_dependency -> dev *(6)* | + +--- + +*(1)* +- Regex: `r'gem\.author[s]?\s*=\s*(?P"[^"]*"|\[[^\]]*\])'` +- Example: +``` + s.authors = [ + "André Arko", "Samuel Giddins", "Colby Swandale", "Hiroshi Shibata" + ] +``` +``` + s.author = "Daniel Garijo" +``` + +*(2)* +- Regex: `r'gem\.description\s*=\s*%q{([^}]+)}|gem\.description\s*=\s*["\']([^"\']+)["\']'` + + +*(3)* +- Regex: `r'gem\.homepage\s*=\s*["\']([^"\']+)["\']` +- Example: `s.homepage = "https://bundler.io"` +- Result: `https://bundler.io` + +*(4)* +- Regex: `r'gem\.license[s]?\s*=\s*["\']([^"\']+)["\']'` +- if license with spdx_id: +``` + name + value + spdx_id +``` +- if not just value +- Example: `gem.license = 'MIT'` +- Result: `MIT` + +*(5)* +- Regex: `r'gem\.name\s*=\s*["\']([^"\']+)["\']` +- Example: `gem.name = "bootstrap-datepicker-rails"` +- Resutl: `bootstrap-datepicker-rails` + +*(5)* +- Regex1: `r'gem\.requirements\s*=\s*(\[.*?\])'` +- Example: +``` +spec.requirements = [ + "Java Development Kit (JDK) 1.6 or newer is required.", + "The environment variable JAVA_HOME must be correctly defined." +] + +``` +- Result: `["Java Development Kit (JDK) 1.6 or newer is required.","The environment variable JAVA_HOME must be correctly defined."]` +- Regex2: `r'gem\.add_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?'` +- Regex3: `'gem\.add_development_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?'` +- Example: +``` + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" +``` +Result: add_depency --> type runtime; add_development_dependencyd --> type dev +``` + [{'result': {'value': 'railties: >= 3.0', 'name': 'railties', 'version': '>= 3.0', 'type': 'Software_application', 'dependency_type': 'runtime'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/bootstrap-datepicker-rails.gemspec'}, {'result': {'value': 'bundler: >= 1.0', 'name': 'bundler', 'version': '>= 1.0', 'type': 'Software_application', 'dependency_type': 'dev'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/bootstrap-datepicker-rails.gemspec'}] +``` + + + + + diff --git a/docs/gemspec.md b/docs/gemspec.md new file mode 100644 index 0000000..b55cbd0 --- /dev/null +++ b/docs/gemspec.md @@ -0,0 +1,86 @@ +The following metadata fields can be extracted from a gemspec file. +These fields are defined in the [Ruby Gems specification](https://guides.rubygems.org/specification-reference/) currently at version **2.0**, and are mapped according to the [CodeMeta crosswalk for ruby gems](https://github.com/codemeta/codemeta/blob/master/crosswalks/Ruby%20Gem.csv). + +| Software metadata category | SOMEF metadata JSON path | .gemspec metadata file field | +|-------------------------------|--------------------------------|--------------------------------------| +| authors | authors[i].result.value | gem.authors *(1)* | +| description | description[i].resultvalue | description *(2)* | +| has_package_file | has_package_file[i].result.value | URL of the filename.gemspec file | +| homepage | homepage[i].result.value | homepage *(3)* | +| license - value | license[i].result.value | license/licenses *(4)* | +| license - spdx id | license[i].result.spdx_id | license/licenses *(4)* spdx_id | +| license - name | license[i].result.name | llicense/licenses name *(4)* | +| package_id | package_id[i].result.value | name *(5)* | +| requirements - value | requirements[i].result.value | requirements/add_dependency/add_development_dependency name:version *(6)* | +| requirements - name | requirements[i].result.name | requirements/add_dependency/add_development_dependency name *(6)* | +| requirements - version | requirements[i].result.version | requirements/add_dependency/add_development_dependency version *(6)* | +| requirements - development type | requirements[i].result.development_type | add_dependency -> runtime *(6)* | +| requirements - development type | requirements[i].result.development_type | add_development_dependency -> dev *(6)* | + +--- + +*(1)* +- Regex: `r'gem\.author[s]?\s*=\s*(?P"[^"]*"|\[[^\]]*\])'` +- Example: +``` + s.authors = [ + "André Arko", "Samuel Giddins", "Colby Swandale", "Hiroshi Shibata" + ] +``` +``` + s.author = "Daniel Garijo" +``` + +*(2)* +- Regex: `r'gem\.description\s*=\s*%q{([^}]+)}|gem\.description\s*=\s*["\']([^"\']+)["\']'` + + +*(3)* +- Regex: `r'gem\.homepage\s*=\s*["\']([^"\']+)["\']` +- Example: `s.homepage = "https://bundler.io"` +- Result: `https://bundler.io` + +*(4)* +- Regex: `r'gem\.license[s]?\s*=\s*["\']([^"\']+)["\']'` +- if license with spdx_id: +``` + name + value + spdx_id +``` +- if not just value +- Example: `gem.license = 'MIT'` +- Result: `MIT` + +*(5)* +- Regex: `r'gem\.name\s*=\s*["\']([^"\']+)["\']` +- Example: `gem.name = "bootstrap-datepicker-rails"` +- Resutl: `bootstrap-datepicker-rails` + +*(5)* +- Regex1: `r'gem\.requirements\s*=\s*(\[.*?\])'` +- Example: +``` +spec.requirements = [ + "Java Development Kit (JDK) 1.6 or newer is required.", + "The environment variable JAVA_HOME must be correctly defined." +] + +``` +- Result: `["Java Development Kit (JDK) 1.6 or newer is required.","The environment variable JAVA_HOME must be correctly defined."]` +- Regex2: `r'gem\.add_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?'` +- Regex3: `'gem\.add_development_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?'` +- Example: +``` + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" +``` +Result: add_depency --> type runtime; add_development_dependencyd --> type dev +``` + [{'result': {'value': 'railties: >= 3.0', 'name': 'railties', 'version': '>= 3.0', 'type': 'Software_application', 'dependency_type': 'runtime'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/bootstrap-datepicker-rails.gemspec'}, {'result': {'value': 'bundler: >= 1.0', 'name': 'bundler', 'version': '>= 1.0', 'type': 'Software_application', 'dependency_type': 'dev'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/bootstrap-datepicker-rails.gemspec'}] +``` + + + + + diff --git a/docs/index.md b/docs/index.md index f6e1671..fdf438d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,19 +1,35 @@ -# Software Metadata Extraction Framework (SOMEF-core) [![Python](https://img.shields.io/pypi/pyversions/somef.svg?style=plastic)](https://badge.fury.io/py/somef) [![PyPI](https://badge.fury.io/py/somef.svg)](https://badge.fury.io/py/somef) [![DOI](https://zenodo.org/badge/190487675.svg)](https://zenodo.org/badge/latestdoi/190487675) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/KnowledgeCaptureAndDiscovery/somef/HEAD?filepath=notebook%2FSOMEF%20Usage%20Example.ipynb) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +# Software Metadata Extraction Framework (SOMEF) [![Python](https://img.shields.io/pypi/pyversions/somef.svg?style=plastic)](https://badge.fury.io/py/somef) [![PyPI](https://badge.fury.io/py/somef.svg)](https://badge.fury.io/py/somef) [![DOI](https://zenodo.org/badge/190487675.svg)](https://zenodo.org/badge/latestdoi/190487675) [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/KnowledgeCaptureAndDiscovery/somef/HEAD?filepath=notebook%2FSOMEF%20Usage%20Example.ipynb) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) **Authors:** Daniel Garijo, Allen Mao, Miguel Ángel García Delgado, Haripriya Dharmala, Vedant Diwanji, Jiaying Wang, Aidan Kelley and Jenifer Tabita Ciuciu-Kiss. -The aim of SOMEF-core is to help automatically extract metadata from scientific software from their readme files and GitHub repositories and make it available in a machine-readable manner. Thanks to SOMEF, we can populate knowedge graphs of scientific software metadata and relate different software together. +The aim of SOMEF is to help automatically extract metadata from scientific software from their readme files and GitHub repositories and make it available in a machine-readable manner. Thanks to SOMEF, we can populate knowedge graphs of scientific software metadata and relate different software together. -SOMEF-core has currently been tested with GitHub repositories, but it can extract metadata from any readme file written in mardown syntax. +SOMEF has currently been tested with GitHub repositories, but it can extract metadata from any readme file written in mardown syntax. !!! info If you experience any issues when using SOMEF, please open an issue on our [GitHub repository](https://github.com/KnowledgeCaptureAndDiscovery/somef/issues). ## Features -Given a readme file (or a GitHub repository) SOMEF-core will extract the following categories (if present): +Given a readme file (or a GitHub repository) SOMEF will extract the following categories (if present): - **Acknowledgement**: Text acknowledging funding sources or contributors +- **Application domain**: The application domain of the repository. This may be related to the research area of a software component (e.g., Astrophysics) or the general domain/functionality of the tool (i.e., machine learning projects)[1](#myfootnote1) +- **Assets**: files attached to the release + - url: URL of the publication of the file + - name: name of the file + - content_size: file size + - content_url: direct download link for the release file + - encoding_format: format of the file + - upload_date: date of publishing + - download_count: numbers of downloads +- **Authors**: Person(s) or organization(s) responsible for the project. We recognize the following properties: + - Name: name of the author (including last name) + - Given name: First name of an author + - Family name: Last name of an author + - Email: email of author + - URL: website or ORCID associated with the author + - Affiliation: name of organization or affiliation - **Build file**: Build file(s) of the project. For example, files used to create a Docker image for the target software, package files, etc. - **Citation**: Preferred citation as the authors have stated in their readme file. SOMEF recognizes Bibtex, Citation File Format files and other means by which authors cite their papers (e.g., by in-text citation). We aim to recognize the following properties: - Title: Title of the publication @@ -38,7 +54,8 @@ Given a readme file (or a GitHub repository) SOMEF-core will extract the followi - **Forks url**: Links to forks made of the project - **Full name**: Name + owner (owner/name) - **Full title**: If the repository is a short name, we will attempt to extract the longer version of the repository name -- **Identifier**: Identifier associated with the software (if any), such as Digital Object Identifiers. DOIs associated with publications will also be detected. +- **Homepage**: URL of the item. +- **Identifier**: Identifier associated with the software (if any), such as Digital Object Identifiers and Software Heritage identifiers (SWH). DOIs associated with publications will also be detected. - **Images**: Images used to illustrate the software component - **Installation instructions**: A set of instructions that indicate how to install a target repository - **Invocation**: Execution command(s) needed to run a scientific software component @@ -47,12 +64,14 @@ Given a readme file (or a GitHub repository) SOMEF-core will extract the followi - **License**: License and usage terms of a software component - **Logo**: Main logo used to represent the target software component - **Name**: Name identifying a software component +- **Ontologies**: URL and path to the ontology files present in the repository - **Owner**: Name and type of the user or organization in charge of the repository - **Package distribution**: Links to package sites like pypi in case the repository has a package available. - **Package files**: Links to package files used to wrap the project in a package. - **Programming languages**: Languages used in the repository - **Related papers**: URL to possible related papers within the repository stated within the readme file (from Arxiv) -- **Releases** (GitHub only): Pointer to the available versions of a software component. For each release, somef will track the following properties: +- **Releases** (GitHub and Gitlab): Pointer to the available versions of a software component. For each release, somef will track the following properties: + - Assets: files attached to the release - Description: Release notes - Author: Agent responsible of creating the release - Name: Name of the release @@ -64,12 +83,17 @@ Given a readme file (or a GitHub repository) SOMEF-core will extract the followi - Link to the tarball zip and code of the release - **Repository status**: Repository status as it is described in [repostatus.org](https://www.repostatus.org/). - **Requirements**: Pre-requisites and dependencies needed to execute a software component +- **Run**: Running instructions of a software component. It may be wider than the `invocation` category, as it may include several steps and explanations. +- **Runtime platform**: specifies runtime platform or script interpreter dependencies required to run the project. +- **Script files**: Bash script files contained in the repository - **Stargazers count**: Total number of stargazers of the project - **Support**: Guidelines and links of where to obtain support for a software component - **Support channels**: Help channels one can use to get support about the target software component +- **Type**: type of software (command line application, notebook, ontology, scientific workflow, etc.) - **Usage examples**: Assumptions and considerations recorded by the authors when executing a software component, or examples on how to use it +- **Workflows**: URL and path to the computational workflow files present in the repository -We use different supervised classifiers, header analysis, regular expressions, the GitHub/Gitlab API to retrieve all these fields (more than one technique may be used for each field) and language specific metadata parsers (e.g., for package files). Each extraction records its provenance, with the confidence and technique used on each step. For more information check the [output format description](https://somef-core.readthedocs.io/en/latest/) +We use different supervised classifiers, header analysis, regular expressions, the GitHub/Gitlab API to retrieve all these fields (more than one technique may be used for each field) and language specific metadata parsers (e.g., for package files). Each extraction records its provenance, with the confidence and technique used on each step. For more information check the [output format description](https://somef.readthedocs.io/en/latest/output/) 1 The available application domains currently are: @@ -87,6 +111,9 @@ We use different supervised classifiers, header analysis, regular expressions, t ### GitHub API We use the [Github's API](https://developer.github.com/v3/) to retrieve some of metadata fields indicated above, like name, license changelog and releases of a software component. +### Scikit Learn +[Scikit Learn](https://scikit-learn.org/stable/about.html) is a powerful machine learning framework that provides a variety of methods for supervised and unsupervised learning. We use some of these classifiers to train sentence-based models to detect software description, citation, installation instructions and invocation commands. + ### Wordnet [Wordnet](https://wordnet.princeton.edu/) is a public lexical database which we use to find synonyms of common headers used when describe software. @@ -96,5 +123,5 @@ The JavaScript Object Notation (JSON) is a syntax for storing and exchanging dat ### RDF We use the Resource Description Framework (RDF) to serialize our results. We currently provide two different serializations: [JSON-LD](https://www.w3.org/TR/json-ld11/) and [Turtle](https://www.w3.org/TR/turtle/). The main difference between the JSON and RDF serializations is that they are simpler and do not incorporate the confidence of the results. -SOMEF-core uses the [Software Description Ontology](https://w3id.org/okn/o/sd), which extends [Schema.org](https://schema.org) and [Codemeta](https://codemeta.github.io/terms/). We also support a Codemeta-specific export. +SOMEF uses the [Software Description Ontology](https://w3id.org/okn/o/sd), which extends [Schema.org](https://schema.org) and [Codemeta](https://codemeta.github.io/terms/). We also support a Codemeta-specific export. diff --git a/docs/install.md b/docs/install.md index 5187b21..7be3c4b 100644 --- a/docs/install.md +++ b/docs/install.md @@ -4,11 +4,8 @@ ## Install from Pypi -SOMEF [is available in Pypi!](https://pypi.org/project/somef/). To install it just type: -``` -pip install somef -``` +We are currently working on this ## Install from GitHub To run SOMEF, please follow the next steps: diff --git a/docs/julia 2.md b/docs/julia 2.md new file mode 100644 index 0000000..1f09193 --- /dev/null +++ b/docs/julia 2.md @@ -0,0 +1,36 @@ +The following metadata fields can be extracted from a Pyproject.toml file with Julia. +These fields are defined in the [Julia projects specification](https://docs.julialang.org/en/v1/) currently at version **1.12**, and are mapped according to the [CodeMeta crosswalk for julia projects](https://github.com/codemeta/codemeta/blob/master/crosswalks/Julia%20Project.csv). + +| Software metadata category | SOMEF metadata JSON path | julia pyproject.toml metadata file field | +|-------------------------------|--------------------------------|---------------------------------------------------| +| authors - name | authors[i].result.name | authors *(1)* | +| authors - email | authors[i].result.email | authors *(1)* | +| package_id | package_id[i].result.value | name | +| has_package_file | has_package_file[i].result.value | URL of the Project.toml file | +| identifier | identifier[i].result .value | uuid | +| package_id | package_id[i].result.value | name | +| requirements | requirements[i].result.value | deeps | +| runtime_platform - value | runtime_platform[i].result.value | properties compat | +| runtime_platform - name | runtime_platform[i].result.name | compat | +| version | version[i].result .value | version | + + +--- + + +*(1)* +- Regex: `r'^(.+?)\s*<(.+?)>$''` +- Example: +``` +authors = [ + "Author1 ", + .... + ] + +``` +- Result: +``` +"name": "Author1", +"email": "author1@example.com", +``` + diff --git a/docs/julia.md b/docs/julia.md new file mode 100644 index 0000000..1f09193 --- /dev/null +++ b/docs/julia.md @@ -0,0 +1,36 @@ +The following metadata fields can be extracted from a Pyproject.toml file with Julia. +These fields are defined in the [Julia projects specification](https://docs.julialang.org/en/v1/) currently at version **1.12**, and are mapped according to the [CodeMeta crosswalk for julia projects](https://github.com/codemeta/codemeta/blob/master/crosswalks/Julia%20Project.csv). + +| Software metadata category | SOMEF metadata JSON path | julia pyproject.toml metadata file field | +|-------------------------------|--------------------------------|---------------------------------------------------| +| authors - name | authors[i].result.name | authors *(1)* | +| authors - email | authors[i].result.email | authors *(1)* | +| package_id | package_id[i].result.value | name | +| has_package_file | has_package_file[i].result.value | URL of the Project.toml file | +| identifier | identifier[i].result .value | uuid | +| package_id | package_id[i].result.value | name | +| requirements | requirements[i].result.value | deeps | +| runtime_platform - value | runtime_platform[i].result.value | properties compat | +| runtime_platform - name | runtime_platform[i].result.name | compat | +| version | version[i].result .value | version | + + +--- + + +*(1)* +- Regex: `r'^(.+?)\s*<(.+?)>$''` +- Example: +``` +authors = [ + "Author1 ", + .... + ] + +``` +- Result: +``` +"name": "Author1", +"email": "author1@example.com", +``` + diff --git a/docs/output.md b/docs/output.md index 45f5a7f..7a04879 100644 --- a/docs/output.md +++ b/docs/output.md @@ -1,9 +1,9 @@ -SOMEF-core supports three main output formats. Each of them contains different information with different levels of granularity. Below we enumerate them from more granular to less granular: +SOMEF supports three main output formats. Each of them contains different information with different levels of granularity. Below we enumerate them from more granular to less granular: ## JSON format **Version:** 1.0.1 -Default SOMEF-core response (and more complete in terms of metadata). The JSON format returns a set of categories, as shown in the snippet below: +Default SOMEF response (and more complete in terms of metadata). The JSON format returns a set of categories, as shown in the snippet below: ```json { @@ -66,6 +66,7 @@ The `confidence` depends on the `technique` used. In this case, the confidence i SOMEF aims to recognize the following categories (in alphabetical order): - `acknowledgement`: Any text that the authors have prepared to acknnowledge the contribution from others, or project funding. +- `application_domain`: The application domain of the repository. This may be related to the research area of a software component (e.g., Astrophysics) or the general domain/functionality of the tool (i.e., machine learning projects). See all current recognized application domains [here](https://somef.readthedocs.io/en/latest/#myfootnote1). - `authors`: Person or organization responsible of the project. This property is also used to indicate the responsible entities of a publication associated with the code repository. - `citation`: Software citation (usually in `.bib` form) as the authors have stated in their readme file, or through a `CFF` file. - `code_of_conduct`: Link to the code of conduct file of the project @@ -77,6 +78,7 @@ SOMEF aims to recognize the following categories (in alphabetical order): - `date_created`: Date when the software component was created. - `date_updated`: Date when the software component was last updated (note that this will always be older than the date of the extraction). - `description`: A description of what the software component does. +- `development_status`: The project’s development stage: beta, deprecated... - `documentation`: Where to find additional documentation about a software component. - `download_url`: URL where to download the target software (typically the installer, package or a tarball to a stable version) - `executable_example`: Jupyter notebooks ready for execution (e.g., through myBinder, colab or files) @@ -87,6 +89,7 @@ SOMEF aims to recognize the following categories (in alphabetical order): - `full_title`: If the repository has a short name, we will attempt to extract the longer version of the repository name. For example, a repository may be called "Widoco", but the longer title is "Wizard for documenting ontologies". - `has_build_file`: Build file to create a Docker image for the target software - `has_script_file`: Snippets of code contained in the repository. +- `homepage`: URL of the item. - `identifier`: Identifiers detected within a repository (e.g., Digital Object Identifier). - `images`: Images used to illustrate the software component. - `installation`: A set of instructions that indicate how to install a target repository @@ -96,6 +99,7 @@ SOMEF aims to recognize the following categories (in alphabetical order): - `license`: License and usage terms of a software component - `logo`: Main logo used to represent the target software component. - `name`: Name identifying a software component +- `ontologies`: URL and path to the ontology files present in the repository. - `owner`: Name of the user or organization in charge of the repository - `package_distribution`: Link to official package repositories where the software can be downloaded from (e.g., `pypi`). - `package_file`: Link to a package file used in the repository (e.g., `pyproject.toml`, `setup.py`). @@ -112,6 +116,11 @@ SOMEF aims to recognize the following categories (in alphabetical order): - `type`: Software type: Commandline Application, Notebook Application, Ontology, Scientific Workflow. Non-Software types: Static Website, Uncategorized - `usage`: Usage examples and considerations of a code repository. - `workflows`: URL and path to the computational workflow files present in the repository. +- `homepage`: URL to the homepage of the software or organization. +- `reference_publication`: URL to the paper associated with the code repository. +- `package_id`: Identifier extracted from packages. (e.g., `packages.json`) +- `funding`: Funding code for the related project. +- `has_package_file`: Specifies what package file is present in the code repository. The following table summarized the properties used to describe a `category`: @@ -162,7 +171,7 @@ The following object `types` are currently supported: - `Agent`: user (typically, a person) or organization responsible for authoring a software release or a paper. - `Publication`: Scientific paper associated with the code repository. - `SoftwareApplication`: Class to represent software dependencies between projects. - +- `Runtime_platform`: specifies runtime platform or script interpreter dependencies required to run the project.. The following literal types are currently supported: - `Number`: A numerical value. We do not distinguish between integer, long or float. @@ -172,6 +181,8 @@ The following literal types are currently supported: - `File_dump`: The value is a string with the contents of a file (e.g., a `citation.cff` file, or a `license.md` file). - `Url`: uniform resource locator of a file. + + + + +The tables below summarizes all types and their corresponding properties- + +An AGENT has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **email** | String | Email of an author | +| **family_name** | String | Last name of an author | +| **given_name** | String | First name of an author | +| **name** | String | Name used to designate the person or organization| +| **url** | Url | Uniform resource locator of the resource | +| **affiliation** | String | name of organization or affiliation | +| **identifier** | String | id of an agent | +| **role** | String | role of agent | + +An ASSET has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **content_size** | Integer | size of file | +| **content_url** | String | direct download link for the release file | +| **download_count** | Integer | numbers of downloads | +| **encoding_format** | String | format of the file | +| **name** | String | Title or name of the file | +| **upload_date** | Date | Date of creation of a release | +| **url** | Url | Uniform resource locator of the resource | + + + +A LICENSE has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **name** | String | Title or name of the license | +| **spdx_id** | String | Spdx id corresponding to this license | +| **url** | Url | Uniform resource locator of the license | +| **identifier** | String | id of licence | + +A PROGRAMMING_LANGUAGE has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **name** | String | Name of the language | +| **size** | Integer | File size content (bytes) of a code repository using a given programming language | + + +A PUBLICATION has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **author** | Agent, Organization | Person or organization responsible for creating an article or a software release. | +| **doi** | Url | When a publication is detected, but the format is in bibtek or CFF, SOMEF will add a `doi` field with the detected DOI value. The result includes a full URL. | +| **title** | String | Title of the publication | +| **url** | Url | Uniform resource locator of the resource | + + +A RELEASE has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **assets** | Asset | Files attached to the release +| **author** | Agent, Organization | Person or organization responsible for creating an article or a software release. | +| **description** | String | Descriptive text with the purpose of the release | +| **date_created** | Date | Date of creation of a release | +| **date_published** | Date | Date of publication of a release | +| **html_url** | Url | link to the HTML representation of a release | +| **name** | String | Title or name used to designate the release, license user or programming language. | +| **release_id** | String | Id of a software release. | +| **tag** | String | named version of a release | +| **tarball_url** | Url | URL to the tar ball file where to download a software release | +| **url** | Url | Uniform resource locator of the resource | +| **zipball_url** | Url | URL to the zip file where to download a software release | + + + + + +A RUNTIME_PLATFORM has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **name** | String | Name of the runtime platform (e.g., Java) | + **version** | String | version of the runtime platform | +| **value** | String | name and version of the runtime platform | + + +A SCHOLARLY_ARTICLE has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **title** | String | Title of reference or citation | +| **value** | String | Title of reference or citation | +| **url** | String | Link to reference or citation | +| **date_published** | String | date of publication reference or citation | +| **doi** | String | Identifier of reference| + + +A SOFTWARE_APPLICATION has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **name** | String | Name of the software | +| **value** | String | Name and version of the software | +| **version** | String | version of software | +| **development_type** | String | runtime or dev | + +A TEXT_EXCERPT has the following properties: + +| Property | Expected value | Definition | +|---|---|---| +| **original_header** | String | If the result value is extracted from a markdown file like a README, the original header of that section is also returned. | +| **parent_header** | [String] | If the result value is extracted from a markdown file like a README, the parent header(s) of the current section are also returned (in case they exist). | + ### Format @@ -208,10 +340,16 @@ The following formats for a result value are currently recognized: - `docker_compose`: [orchestration file](https://docs.docker.com/compose/compose-file/) used to communicate multiple containers. - `readthedocs`: documentation format used by many repositories in order to describe their projects. - `wiki`: documentation format used in GitHub repositories. -- `setup.py`: package file format used in python projects -- `pyproject.toml`: package file format used in python projects -- `pom.xml`: package file used in Java projects -- `package.json`: package file used in Javascript projects +- `setup.py`: package file format used in python projects. +- `publiccode.yml`: metadata file used to describe public sector software projects. +- `pyproject.toml`: package file format used in python projects. +- `pom.xml`: package file used in Java projects. +- `package.json`: package file used in Javascript projects. +- `bower.json`: package descriptor used for configuring packages that can be used as a dependency for Bower-managed front-end projects. +- `composer.json`: manifest file serves as the package descriptor used in PHP projects. +- `cargo.toml.json`: manifest file serves as the package descriptor used in Rust projects. +- `[name].gemspec`:manifest file serves as the package descriptor used in Ruby gem projects. + ### Technique The techniques can be of several types: diff --git a/docs/packagejson 2.md b/docs/packagejson 2.md new file mode 100644 index 0000000..da5fcc1 --- /dev/null +++ b/docs/packagejson 2.md @@ -0,0 +1,92 @@ +The following metadata fields can be extracted from a package.json file. +These fields are defined in the [Package.json specification](https://docs.npmjs.com/cli/v10/configuring-npm/package-json), currently at version **10.9.4**, and are mapped according to the [CodeMeta crosswalk for package.json](https://github.com/codemeta/codemeta/blob/master/crosswalks/NodeJS.csv). + +| Software metadata category | SOMEF metadata JSON path | PACKAGE.JSON metadata file field | +|-------------------------------|----------------------------------------|--------------------- | +| authors - value | authors[i].result.value | author.name | +| authors - email | authors[i].result.email | author.email | +| authors - url | authors[i].result.url | author.url | +| authors - name | authors[i].result.name | author.name | +| code_repository | code_repository[i].result.value | repository/repository.url/repository.directory *(1)*| +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the package.json file | +| homepage | homepage[i].result.value | homepage | +| issue_tracker | issue_tracker[i].result.value | bugs or bugs.url *(2)* | +| keywords | keywords[i].result.value | keywords | +| license | license[i].result.value | license or license.type *(3)* | +| package_id | package_id[i].result.value | name | +| requirements - value | requirements[i].result.value | dependencies/devDependencies name@sversion *(4)* | +| requirements - name | requirements[i].result.name | dependencies/devDependencies name *(4)* | +| requirements - version | requirements[i].result.version | dependencies/devDependencies version *(4)* | +| runtime_platform - value | runtime_platform[i].result.value | engines(package:version) -> version *(5)* | +| runtime_platform - name | runtime_platform[i].result.name engines(package:version) -> package *(5)* | +| version | version[i].result.value | version | + +--- + +*(1)* +- Example: +``` +"repository": "npm/npm", + +or + +"repository": { +"type": "git", +"url": "git+https://github.com/npm/cli.git" +} + +or + +"repository": { +"type": "git", +"directory": "workspaces/libnpmpublish" +} +``` + +*(2)* +- Example: +``` +"bugs": { +"url": "https://github.com/npm/cli/issues" +} + +or + +"bugs": "https://github.com/npm/cli/issues" + +``` + +*(2)* +- Example: +``` + "license": "Artistic-2.0" + + or + + "license" : { + "type" : "ISC", + "url" : "https://opensource.org/licenses/ISC" + } + ``` +- Result: `Artistic-2.0" or "ISC" (license.type)` + +*(3)* +- Fist part of item -> name; second part --> version +- Example: +``` + "devDependencies": + "foo": "1.0.0 - 2.9999.9999", + ... +``` +Resutl: +```{'result': {'value': 'foo@1.0.0 - 2.9999.9999', 'name': 'foo', 'version': '1.0.0 - 2.9999.9999', 'type': 'Software_application'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'http://example.com/package_neors.json'}``` + +*(5)* +- Example: +``` + "engines": { + "node": ">=0.10.3 <15" + } +``` +- Result: `"name": "Node", "version": "">=0.10.3 <15"` \ No newline at end of file diff --git a/docs/packagejson.md b/docs/packagejson.md new file mode 100644 index 0000000..da5fcc1 --- /dev/null +++ b/docs/packagejson.md @@ -0,0 +1,92 @@ +The following metadata fields can be extracted from a package.json file. +These fields are defined in the [Package.json specification](https://docs.npmjs.com/cli/v10/configuring-npm/package-json), currently at version **10.9.4**, and are mapped according to the [CodeMeta crosswalk for package.json](https://github.com/codemeta/codemeta/blob/master/crosswalks/NodeJS.csv). + +| Software metadata category | SOMEF metadata JSON path | PACKAGE.JSON metadata file field | +|-------------------------------|----------------------------------------|--------------------- | +| authors - value | authors[i].result.value | author.name | +| authors - email | authors[i].result.email | author.email | +| authors - url | authors[i].result.url | author.url | +| authors - name | authors[i].result.name | author.name | +| code_repository | code_repository[i].result.value | repository/repository.url/repository.directory *(1)*| +| description | description[i].result.value | description | +| has_package_file | has_package_file[i].result.value | URL of the package.json file | +| homepage | homepage[i].result.value | homepage | +| issue_tracker | issue_tracker[i].result.value | bugs or bugs.url *(2)* | +| keywords | keywords[i].result.value | keywords | +| license | license[i].result.value | license or license.type *(3)* | +| package_id | package_id[i].result.value | name | +| requirements - value | requirements[i].result.value | dependencies/devDependencies name@sversion *(4)* | +| requirements - name | requirements[i].result.name | dependencies/devDependencies name *(4)* | +| requirements - version | requirements[i].result.version | dependencies/devDependencies version *(4)* | +| runtime_platform - value | runtime_platform[i].result.value | engines(package:version) -> version *(5)* | +| runtime_platform - name | runtime_platform[i].result.name engines(package:version) -> package *(5)* | +| version | version[i].result.value | version | + +--- + +*(1)* +- Example: +``` +"repository": "npm/npm", + +or + +"repository": { +"type": "git", +"url": "git+https://github.com/npm/cli.git" +} + +or + +"repository": { +"type": "git", +"directory": "workspaces/libnpmpublish" +} +``` + +*(2)* +- Example: +``` +"bugs": { +"url": "https://github.com/npm/cli/issues" +} + +or + +"bugs": "https://github.com/npm/cli/issues" + +``` + +*(2)* +- Example: +``` + "license": "Artistic-2.0" + + or + + "license" : { + "type" : "ISC", + "url" : "https://opensource.org/licenses/ISC" + } + ``` +- Result: `Artistic-2.0" or "ISC" (license.type)` + +*(3)* +- Fist part of item -> name; second part --> version +- Example: +``` + "devDependencies": + "foo": "1.0.0 - 2.9999.9999", + ... +``` +Resutl: +```{'result': {'value': 'foo@1.0.0 - 2.9999.9999', 'name': 'foo', 'version': '1.0.0 - 2.9999.9999', 'type': 'Software_application'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'http://example.com/package_neors.json'}``` + +*(5)* +- Example: +``` + "engines": { + "node": ">=0.10.3 <15" + } +``` +- Result: `"name": "Node", "version": "">=0.10.3 <15"` \ No newline at end of file diff --git a/docs/pom 2.md b/docs/pom 2.md new file mode 100644 index 0000000..b03dcda --- /dev/null +++ b/docs/pom 2.md @@ -0,0 +1,114 @@ +The following metadata fields can be extracted from a pom.xml file. +These fields are defined in the [Maven POM specification](https://maven.apache.org/pom.html), currently at version **4.0.0**, and are mapped according to the [CodeMeta crosswalk for Java (Maven)](https://github.com/codemeta/codemeta/blob/master/crosswalks/Java%20(Maven).csv). + +| Software metadata category | SOMEF metadata JSON path | POM.XML metadata file field | +|-------------------------------|---------------------------------------------|----------------------------------| +| authors - value | authors[i].result.value | developers.developer.name | +| authors - name | authors[i].result.name | developers.developer.name | +| authors - email | Aauthors[i].result.email | developers.developer.email | +| authors - url | authors[i].result.url | developers.developer.url | +| authors - affiliation | authors[i].result.affiliation | developers.developer.organization | +| has_package_file | has_package_file[i].result .value | URL of the pom.xml file | +| homepage | homepage[i].result.value | homepage | +| issue_tracker | issue_tracker[i].result .value | issueManagement.url | +| package_distribution - value | package_distribution[i].result value | scm.url *(1)*| +| package_distribution - value | package_distribution[i].result.value | repositories.repository(id) *(2)*| +| package_distribution - name | package_distribution[i].result.name | repositories.repository(name) *(2)*| +| package_distribution - url | package_distribution[i].result.url | repositories.repository(url) *(2)*| +| requirements - value | requirements[i].result.value | dependencies.dependency.grpId.arfifactId *(3)* | +| requirements - name | requirements[i].result.name | dependencies.dependency.arfifactId *(3)* | +| requirements - version | requirements[i].result.version | dependencies.dependency.version *(3)* | +| package_id | package_id[i].result .value | group_id.artifact_id *(4)* | +| runtime_platform - value | runtime_platform[i].result.value | properties extract name version *(5)* | +| runtime_platform - name | runtime_platform[i].result.name | properties extract name *(5)*| +| runtime_platform - value | runtime_platform[i].result.value | properties extract version *(5)* | +| version | version[i].result .value | version | + +--- + +*(1)* +- Example: +``` + + scm:svn:http://127.0.0.1/svn/my-project + scm:svn:https://127.0.0.1/svn/my-project + HEAD + http://127.0.0.1/websvn/my-project + +``` +- Result: +``` +package_distribution': [{'result': {'value': 'http://127.0.0.1/websvn/my-project', 'type': 'Url'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/pom.xml'}] +``` + +*(2)* +- Example: +``` + + + jitpack.io + https://jitpack.io + + +``` +- Result: +``` +'package_distribution': [{ + 'result': { + 'value': 'jitpack.io', + 'url': 'https://jitpack.io', + 'type': 'Url' + } +``` + +*(3)* +- Example: +``` + + + org.apache.maven + maven-model + 3.9.0 + + + +``` +- Result: +``` +'requirements': [{ + 'result': + {'value': 'org.apache.maven.maven-model', + 'name': 'maven-model', + 'version': '3.9.0', + 'type': 'Software_application'}, + +``` + +*(4)* +- Example: +``` + es.oeg + widoco + ``` +- Result: +``` + 'package_id': [{ + 'result': { + 'value': 'es.oeg.widoco', + +``` + + *(5)* + - Example: +``` + + 1.8 + +``` + +- Result: +``` +[{'value': 'Java: 1.8', 'name': 'Java', 'version': '1.8'}] +``` + + diff --git a/docs/pom.md b/docs/pom.md new file mode 100644 index 0000000..b03dcda --- /dev/null +++ b/docs/pom.md @@ -0,0 +1,114 @@ +The following metadata fields can be extracted from a pom.xml file. +These fields are defined in the [Maven POM specification](https://maven.apache.org/pom.html), currently at version **4.0.0**, and are mapped according to the [CodeMeta crosswalk for Java (Maven)](https://github.com/codemeta/codemeta/blob/master/crosswalks/Java%20(Maven).csv). + +| Software metadata category | SOMEF metadata JSON path | POM.XML metadata file field | +|-------------------------------|---------------------------------------------|----------------------------------| +| authors - value | authors[i].result.value | developers.developer.name | +| authors - name | authors[i].result.name | developers.developer.name | +| authors - email | Aauthors[i].result.email | developers.developer.email | +| authors - url | authors[i].result.url | developers.developer.url | +| authors - affiliation | authors[i].result.affiliation | developers.developer.organization | +| has_package_file | has_package_file[i].result .value | URL of the pom.xml file | +| homepage | homepage[i].result.value | homepage | +| issue_tracker | issue_tracker[i].result .value | issueManagement.url | +| package_distribution - value | package_distribution[i].result value | scm.url *(1)*| +| package_distribution - value | package_distribution[i].result.value | repositories.repository(id) *(2)*| +| package_distribution - name | package_distribution[i].result.name | repositories.repository(name) *(2)*| +| package_distribution - url | package_distribution[i].result.url | repositories.repository(url) *(2)*| +| requirements - value | requirements[i].result.value | dependencies.dependency.grpId.arfifactId *(3)* | +| requirements - name | requirements[i].result.name | dependencies.dependency.arfifactId *(3)* | +| requirements - version | requirements[i].result.version | dependencies.dependency.version *(3)* | +| package_id | package_id[i].result .value | group_id.artifact_id *(4)* | +| runtime_platform - value | runtime_platform[i].result.value | properties extract name version *(5)* | +| runtime_platform - name | runtime_platform[i].result.name | properties extract name *(5)*| +| runtime_platform - value | runtime_platform[i].result.value | properties extract version *(5)* | +| version | version[i].result .value | version | + +--- + +*(1)* +- Example: +``` + + scm:svn:http://127.0.0.1/svn/my-project + scm:svn:https://127.0.0.1/svn/my-project + HEAD + http://127.0.0.1/websvn/my-project + +``` +- Result: +``` +package_distribution': [{'result': {'value': 'http://127.0.0.1/websvn/my-project', 'type': 'Url'}, 'confidence': 1, 'technique': 'code_parser', 'source': 'https://example.org/pom.xml'}] +``` + +*(2)* +- Example: +``` + + + jitpack.io + https://jitpack.io + + +``` +- Result: +``` +'package_distribution': [{ + 'result': { + 'value': 'jitpack.io', + 'url': 'https://jitpack.io', + 'type': 'Url' + } +``` + +*(3)* +- Example: +``` + + + org.apache.maven + maven-model + 3.9.0 + + + +``` +- Result: +``` +'requirements': [{ + 'result': + {'value': 'org.apache.maven.maven-model', + 'name': 'maven-model', + 'version': '3.9.0', + 'type': 'Software_application'}, + +``` + +*(4)* +- Example: +``` + es.oeg + widoco + ``` +- Result: +``` + 'package_id': [{ + 'result': { + 'value': 'es.oeg.widoco', + +``` + + *(5)* + - Example: +``` + + 1.8 + +``` + +- Result: +``` +[{'value': 'Java: 1.8', 'name': 'Java', 'version': '1.8'}] +``` + + diff --git a/docs/publiccode 2.md b/docs/publiccode 2.md new file mode 100644 index 0000000..84ab402 --- /dev/null +++ b/docs/publiccode 2.md @@ -0,0 +1,133 @@ +The following metadata fields can be extracted from a publiccode.yml file. +These fields are defined in the [PublicCode specification](https://yml.publiccode.tools/), currently at version **0.5.0**, and are mapped according to the [CodeMeta crosswalk for publiccode.yml](https://codemeta.github.io/crosswalk/publiccode/) and [csv CodeMeta crosswalk for publiccode.yml](https://github.com/codemeta/codemeta/blob/master/crosswalks/publiccode.csv) + +| Software metadata category | SOMEF metadata JSON path | PUBLICCODE.YML metadata file field | +|-----------------------------|---------------------------------------|----------------------------------------| +| application_domain | application_domain[i].result.value | categories or description.[lang].genericName *(1)* | +| code_repository | code_repository[i].result.value | url | +| date_published | date_published[i].result.value | releaseDate | +| date_updated | date_updated[i].result.value | releaseDate | +| description | description[i].result.value | description.[lang].shortDescription or description.[lang].longDescription *(2)* | +| development_status | development_status[i].result.value | developmentStatus | +| has_package_file | has_package_file[i].result.value | URL of the publiccode.yml file | +| keywords | keywords[i].result.value | description.[lang].features *(3)* | +| license - value | license[i].result.value | legal.license *(4)* | +| license - spdx id | license[i].result.spdx_id | legal.license extract spdx id *(4)*| +| license - name | license[i].result.name | legal.license extract name *(4)* | +| name | name[i].result.value | name or description.[lang].localisedName *(5)* | +| requirements - value | requirements[i].result.value | dependsOn.open / dependsOn.proprietary / dependsOn.hardware name + version *(6)* | +| requirements - name | requirements[i].result.name | dependsOn.open / dependsOn.proprietary / dependsOn.hardware name *(6)* | +| requiriments - version | requirements[i].result.version | dependsOn.open / dependsOn.proprietary / dependsOn.hardware more than one label of version *(6)* | +| runtime_platform | runtime_platform[i].result.value | platforms | +| version | version[i].result.value | softwareVersion | + +--- + +*(1)* +- Example: +``` +categories: + - data-collection + - it-development +``` +or +``` +description: + nl: + genericName: API component +``` + +*(2)* +- Example: +``` +description: + nl: + shortDescription: API voor het beheren van objecten + longDescription: > + De **Objecten API** heeft als doel om uiteenlopende objecten eenvoudig te kunnen + registreren en ontsluiten in een gestandaardiseerd formaat. De Objecten API kan + ....`_. + + en: + shortDescription: API to manage objects + longDescription: > + The **Objects API** aims to easily store various objects and make them available in + standardized format. The Objects API can be used by any organization to manage + relevant objects. An organization can also choose to use the Objects API to + ....`_. +``` + +*(3)* +- Example: +``` +description: + nl: + features: + - Objecten API + - Minimalistische objecten beheerinterface + en: + features: + - Objects API + - Minimalistic object management interface +``` + + +*(4)* +- Look for expressions in a local dictionary with all the reference and spdx_id +- Example: +``` +legal: + license: AGPL-3.0-or-later + mainCopyrightOwner: City of Chicago + repoOwner: City of Chicago +``` +-Result: +``` +'result': + {'value': 'AGPL-3.0-or-later', + 'spdx_id': 'AGPL-3.0', + 'name': 'GNU Affero General Public License v3.0', + 'type': 'License'}, + +``` + +*(5)* +- Example: +`name: Medusa` +or +``` +description: + en: + localisedName: Medusa +``` + + +*(6)* +- Examples: +``` +dependsOn: + open: + - name: Objecttypes API + optional: false + version: '1.0' + - name: MySQL + versionMin: "1.1" + versionMax: "1.3" + optional: true + - name: PostgreSQL + versionMin: "14.0" + optional: true +``` + +- Result PostgreSQL: +``` + "result": { + "value": "PostgreSQL>=14.0", + "name": "PostgreSQL", + "version": ">=14.0", + "type": "Software_application", + "dependency_type": "runtime" + }, +``` + + diff --git a/docs/publiccode.md b/docs/publiccode.md new file mode 100644 index 0000000..84ab402 --- /dev/null +++ b/docs/publiccode.md @@ -0,0 +1,133 @@ +The following metadata fields can be extracted from a publiccode.yml file. +These fields are defined in the [PublicCode specification](https://yml.publiccode.tools/), currently at version **0.5.0**, and are mapped according to the [CodeMeta crosswalk for publiccode.yml](https://codemeta.github.io/crosswalk/publiccode/) and [csv CodeMeta crosswalk for publiccode.yml](https://github.com/codemeta/codemeta/blob/master/crosswalks/publiccode.csv) + +| Software metadata category | SOMEF metadata JSON path | PUBLICCODE.YML metadata file field | +|-----------------------------|---------------------------------------|----------------------------------------| +| application_domain | application_domain[i].result.value | categories or description.[lang].genericName *(1)* | +| code_repository | code_repository[i].result.value | url | +| date_published | date_published[i].result.value | releaseDate | +| date_updated | date_updated[i].result.value | releaseDate | +| description | description[i].result.value | description.[lang].shortDescription or description.[lang].longDescription *(2)* | +| development_status | development_status[i].result.value | developmentStatus | +| has_package_file | has_package_file[i].result.value | URL of the publiccode.yml file | +| keywords | keywords[i].result.value | description.[lang].features *(3)* | +| license - value | license[i].result.value | legal.license *(4)* | +| license - spdx id | license[i].result.spdx_id | legal.license extract spdx id *(4)*| +| license - name | license[i].result.name | legal.license extract name *(4)* | +| name | name[i].result.value | name or description.[lang].localisedName *(5)* | +| requirements - value | requirements[i].result.value | dependsOn.open / dependsOn.proprietary / dependsOn.hardware name + version *(6)* | +| requirements - name | requirements[i].result.name | dependsOn.open / dependsOn.proprietary / dependsOn.hardware name *(6)* | +| requiriments - version | requirements[i].result.version | dependsOn.open / dependsOn.proprietary / dependsOn.hardware more than one label of version *(6)* | +| runtime_platform | runtime_platform[i].result.value | platforms | +| version | version[i].result.value | softwareVersion | + +--- + +*(1)* +- Example: +``` +categories: + - data-collection + - it-development +``` +or +``` +description: + nl: + genericName: API component +``` + +*(2)* +- Example: +``` +description: + nl: + shortDescription: API voor het beheren van objecten + longDescription: > + De **Objecten API** heeft als doel om uiteenlopende objecten eenvoudig te kunnen + registreren en ontsluiten in een gestandaardiseerd formaat. De Objecten API kan + ....`_. + + en: + shortDescription: API to manage objects + longDescription: > + The **Objects API** aims to easily store various objects and make them available in + standardized format. The Objects API can be used by any organization to manage + relevant objects. An organization can also choose to use the Objects API to + ....`_. +``` + +*(3)* +- Example: +``` +description: + nl: + features: + - Objecten API + - Minimalistische objecten beheerinterface + en: + features: + - Objects API + - Minimalistic object management interface +``` + + +*(4)* +- Look for expressions in a local dictionary with all the reference and spdx_id +- Example: +``` +legal: + license: AGPL-3.0-or-later + mainCopyrightOwner: City of Chicago + repoOwner: City of Chicago +``` +-Result: +``` +'result': + {'value': 'AGPL-3.0-or-later', + 'spdx_id': 'AGPL-3.0', + 'name': 'GNU Affero General Public License v3.0', + 'type': 'License'}, + +``` + +*(5)* +- Example: +`name: Medusa` +or +``` +description: + en: + localisedName: Medusa +``` + + +*(6)* +- Examples: +``` +dependsOn: + open: + - name: Objecttypes API + optional: false + version: '1.0' + - name: MySQL + versionMin: "1.1" + versionMax: "1.3" + optional: true + - name: PostgreSQL + versionMin: "14.0" + optional: true +``` + +- Result PostgreSQL: +``` + "result": { + "value": "PostgreSQL>=14.0", + "name": "PostgreSQL", + "version": ">=14.0", + "type": "Software_application", + "dependency_type": "runtime" + }, +``` + + diff --git a/docs/pyprojecttoml 2.md b/docs/pyprojecttoml 2.md new file mode 100644 index 0000000..f6c1233 --- /dev/null +++ b/docs/pyprojecttoml 2.md @@ -0,0 +1,78 @@ +The following metadata fields can be extracted from a pyproject.toml file. +These fields are defined in the [pyproject.toml specification](https://packaging.python.org/en/latest/guides/writing-pyproject-toml), and are mapped according to the [CodeMeta crosswalk for python](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | PYPROJECT.TOML metadata file field | +|--------------------------------|-----------------------------|----------------------------------------| +| authors - value | authors[i].result.value | authors.name | +| authors - email | authors[i].result.email | authors.email | +| authors - name | authors[i].result.name | authors.name | +| authors - url | authors[i].result.url | authors.url | +| code_repository | code_repository[i].result.value | project.urls.repository or tool.poetry.repository | +| description | description[i].result.value | project.description or tool.poetry.description | +| documentation | documentation[i].result.value | project.urls.documentation or tool.poetry.documentation | +| download_url | download_url[i].result.value | project.urls.download or tool.poetry.download| +| license - value | license[i].result.value | license.file or license.type or license | +| license - name | license[i].result.name | license.name *(1)* | +| license - spdx id | license[i].result.spdx_id | license.identifier if "spdx.org/licenses/ *(1)* | +| has_package_file | has_package_file[i].result.value | URL of the pyproject.toml file | +| homepage | homepage[i].result.value | project.homepage or tool.poetry.homepage | +| issue_tracker | issue_tracker[i].result.value | projects.urls.issue or tool.poetry.issue | +| keywords | keywords[i].result.value | keywords | +| package_id | package_id[i].result.value | project.name or tool.poetry.name | +| readme_url | readme_url[i].result.value | projects.urls.readme or tool.poetry.readme| +| related_documentation | download_url[i].result.value | projects.urls or tool.poetry | +| requirements - value | requirements[i].result.value | dependencies(name=version) or build-system.requires[i] *(2)* | +| requirements - name | requirements[i].result.name | dependencies(name=version) -> dependencies.name or build-system.requires[i] parsing -> name *(2)* | +| requirements - version | requirements[i].result.version | dependencies[i](name=version) -> dependencies.version or build-system.requires[i] parsing -> version *(2)* | +| runtime_platform - value | runtime_platform[i].result.value | depeendencies or requires-python -> version *(3)* | +| runtime_platform - name | runtime_platform[i].result.name | depeendencies or requires-python -> name *(3)* | +| version - value | version[i].result.value | project.version or tool.poetry.version | +| version - tag | version[i].result.tag | project.version or tool.poetry.version | + +--- + +*(1)* +- Look for the name and spdx_id in a local dictionary with all licenses + +*(2)* +- Examples: allows formats +``` +dependencies = [ + "astropy", + "ctapipe", + "ctaplot", + "dl1_data_handler", + "h5py", +........ + +[tool.poetry.dependencies] + python = ">=3.9,<=3.13" + bs4 = "^0.0.1" +........ + +[build-system] + requires = ["poetry-core>=1.1.10"] +``` + +- If it is possible we obtain name and version + 'value' : 'python>=3.9,<=3.13' + 'name' : 'python' + 'version' : '>=3.9,<=3.13' + +*(3)* +- Always "Python" and version if exists. +- Examenple: +``` +requires-python = ">=3.11" + +or + +[tool.poetry.dependencies] + python = ">=3.9,<=3.13" + +or + +[dependencies] + python = ">=3.9,<=3.13" + +``` diff --git a/docs/pyprojecttoml.md b/docs/pyprojecttoml.md new file mode 100644 index 0000000..f6c1233 --- /dev/null +++ b/docs/pyprojecttoml.md @@ -0,0 +1,78 @@ +The following metadata fields can be extracted from a pyproject.toml file. +These fields are defined in the [pyproject.toml specification](https://packaging.python.org/en/latest/guides/writing-pyproject-toml), and are mapped according to the [CodeMeta crosswalk for python](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | PYPROJECT.TOML metadata file field | +|--------------------------------|-----------------------------|----------------------------------------| +| authors - value | authors[i].result.value | authors.name | +| authors - email | authors[i].result.email | authors.email | +| authors - name | authors[i].result.name | authors.name | +| authors - url | authors[i].result.url | authors.url | +| code_repository | code_repository[i].result.value | project.urls.repository or tool.poetry.repository | +| description | description[i].result.value | project.description or tool.poetry.description | +| documentation | documentation[i].result.value | project.urls.documentation or tool.poetry.documentation | +| download_url | download_url[i].result.value | project.urls.download or tool.poetry.download| +| license - value | license[i].result.value | license.file or license.type or license | +| license - name | license[i].result.name | license.name *(1)* | +| license - spdx id | license[i].result.spdx_id | license.identifier if "spdx.org/licenses/ *(1)* | +| has_package_file | has_package_file[i].result.value | URL of the pyproject.toml file | +| homepage | homepage[i].result.value | project.homepage or tool.poetry.homepage | +| issue_tracker | issue_tracker[i].result.value | projects.urls.issue or tool.poetry.issue | +| keywords | keywords[i].result.value | keywords | +| package_id | package_id[i].result.value | project.name or tool.poetry.name | +| readme_url | readme_url[i].result.value | projects.urls.readme or tool.poetry.readme| +| related_documentation | download_url[i].result.value | projects.urls or tool.poetry | +| requirements - value | requirements[i].result.value | dependencies(name=version) or build-system.requires[i] *(2)* | +| requirements - name | requirements[i].result.name | dependencies(name=version) -> dependencies.name or build-system.requires[i] parsing -> name *(2)* | +| requirements - version | requirements[i].result.version | dependencies[i](name=version) -> dependencies.version or build-system.requires[i] parsing -> version *(2)* | +| runtime_platform - value | runtime_platform[i].result.value | depeendencies or requires-python -> version *(3)* | +| runtime_platform - name | runtime_platform[i].result.name | depeendencies or requires-python -> name *(3)* | +| version - value | version[i].result.value | project.version or tool.poetry.version | +| version - tag | version[i].result.tag | project.version or tool.poetry.version | + +--- + +*(1)* +- Look for the name and spdx_id in a local dictionary with all licenses + +*(2)* +- Examples: allows formats +``` +dependencies = [ + "astropy", + "ctapipe", + "ctaplot", + "dl1_data_handler", + "h5py", +........ + +[tool.poetry.dependencies] + python = ">=3.9,<=3.13" + bs4 = "^0.0.1" +........ + +[build-system] + requires = ["poetry-core>=1.1.10"] +``` + +- If it is possible we obtain name and version + 'value' : 'python>=3.9,<=3.13' + 'name' : 'python' + 'version' : '>=3.9,<=3.13' + +*(3)* +- Always "Python" and version if exists. +- Examenple: +``` +requires-python = ">=3.11" + +or + +[tool.poetry.dependencies] + python = ">=3.9,<=3.13" + +or + +[dependencies] + python = ">=3.9,<=3.13" + +``` diff --git a/docs/readmefile 2.md b/docs/readmefile 2.md new file mode 100644 index 0000000..adad749 --- /dev/null +++ b/docs/readmefile 2.md @@ -0,0 +1,163 @@ +The following metadata fields can be extracted from a readme.md file. +Unlike others files formats (pom, cargo, cabal...), README documents do not follow a formal specification. They are free‑form text files, usually written in markdown or restructuredtext, and their structure varies widely across projects. SOMEF applies heuristics to identify common sections (e.g., Title, Description, Installation, Usage, License...) and extracts metadata accordingly. + +| Software metadata category | SOMEF metadata JSON path | README.MD metadata file field | +|--------------------------------|----------------------------------------|----------------------------------------| +| acknowledgement | acknowledgement[i].result.value | hearders with acknowledgement | +| citation | citation[i].result.value | headers with citation, reference, cite. Extract bibtext **(1)** | +| contact | contact[i].result.value | headers with contact | +| contributing_guidelines | contributing_guidelines[i].result.value | headers with contributing | +| contributors | contributors[i].result.value | headers with contributor | +| description | description[i].result.value | headers with description, introduction, basics, initiation, overview | +| documentation | documentation[i].result.value | github or gitlab url documentation **(2)**, headers with documentation, readthedocs same name project, readthedocs in badges, wiki links in badges and text | +| download | download[i].result.value | headers with download | +| executable_example | executable_example[i].result.value | extracts Binder from badgets **(3)** | +| faq | faq[i].result.value | headers with faq, errors, problems | +| full_title | full_title[i].result.value | extract full title **(4)** | +| homepage | homepage[i].result.value | homepage from badgets **(5)** | +| identifier | idenfier[i].result.value | extract from badgets directly or get from zenodo with latest doi **(6)**, swh identifiers **(7)** | +| images | images[i].result.value | other images in the README apart from the logo | +| installation | installation[i].result.value | headers with installation, install, setup, prepare, preparation, manual, guide | +| license | license[i].result.value | headers with license | +| logo | logo[i].result.value | look images in badges and text **(8)** | +| package_distribution | package_distribution[i].result.value | Pypi or latest Pypi version in badges **(9)** | +| related_documentation | dorelated_documentationumentation[i].result.value | readthedocs diferent name project | +| run | run[i].result.value | headers with run, execute | +| readme_url | readme_url[i].result.value | url in raw githubuser content **(10)** | +| related_papers | related_papers[i].result.value | look for arXiv reference in all the text **(11)** | +| repository_status | repository_status[i].result.value | badges with Project status **(12)** | +| requirements | requirements[i].result.value | headers with requirement, prerequisite, dependency, dependent | +| support | support[i].result.value | headers with support, help, report | +| support_channels | support_channels[i].result.value | extract information of gitter, reddit and discord in badges and text **(13)** | +| usage | usage[i].result.value | headers with usage, example, implement, implementation, demo, tutorial, start, started | + + +------ + +**(1)** +- Example: +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +- Result: +``` +{ + "result": { + "value": "@inproceedings{garijo2017widoco,\n url = {http://dgarijo.com/papers/widoco-iswc2017.pdf},\n funding = {USNSF ICER-1541029, NIH 1R01GM117097-01},\n doi = {10.1007/978-3-319-68204-4_9},\n organization = {Springer, Cham},\n year = {2017},\n pages = {94--102},\n booktitle = {International Semantic Web Conference},\n author = {Garijo, Daniel},\n title = {WIDOCO: a wizard for documenting ontologies},\n}", + "type": "Text_excerpt", + "format": "bibtex", + "doi": "10.1007/978-3-319-68204-4_9", + "title": "WIDOCO: a wizard for documenting ontologies", + "author": "Garijo, Daniel", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf" + }, +} +``` + + +**(2)** +- Example if github: +``` +f"https://github.com/{owner}/{repo_name}/tree/{urllib.parse.quote(repo_default_branch)}/{docs_path}" +``` +- Example if gitlab: +``` +f"https://{domain_gitlab}/{owner}/{repo_name}/-/tree/{urllib.parse.quote(repo_default_branch)}/{docs_path}" +``` + +**(3)** +- Example: `[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/user/repo/HEAD)` +- Result: `"value": "https://mybinder.org/v2/gh/user/repo/HEAD"` + +**(4)** +- Example: `# WIzard for DOCumenting Ontologies (WIDOCO)` +- Result: +``` +"full_title": [ + { + "result": { + "type": "String", + "value": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } +] +``` + +**(5)** +- Example: `[![Project homepage](https://img.shields.io/badge/homepage-project-blue)](https://myproject.org)` +- Result: `"value": "https://myproject.org"` + + +**(6)** +- Example: `[![DOI](https://zenodo.org/badge/11427075.svg)](https://doi.org/10.5281/zenodo.11093793)` +- Result: `"value": "https://doi.org/10.5281/zenodo.11093793"` + +**(7)** +- Example: `[![SWH](https://archive.softwareheritage.org/badge/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7/)](https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7;origin=...)` +- Result: ` "value": "https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7",` + + +**(8)** +- Example: `![Logo](src/main/resources/logo/logo2.png)` +- Result: `"value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png"`` + +**(9)** +- Example: `[![PyPI](https://badge.fury.io/py/somef.svg)](https://badge.fury.io/py/somef) ` +- Result: `"value": "https://pypi.org/project/somef"` + + +**(10)** +- Example: +``` +[Yulun Zhang](http://yulunzhang.com/), [Yapeng Tian](http://yapengtian.org/), [Yu Kong](http://www1.ece.neu.edu/~yukong/), [Bineng Zhong](https://scholar.google.de/citations?user=hvRBydsAAAAJ&hl=en), and [Yun Fu](http://www1.ece.neu.edu/~yunfu/), "Residual Dense Network for Image Super-Resolution", CVPR 2018 (spotlight), [[arXiv]](https://arxiv.org/abs/1802.08797) +``` +- Result: `"value": "https://arxiv.org/abs/1802.08797"` + + +**(11)** +- Example: +``` +f"https://raw.githubusercontent.com/{owner}/{repo_name}/{repo_ref}/{urllib.parse.quote(partial)}" +``` + +**(12)** +- Example: +``` + [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +``` +- Result: +``` +"value": "https://www.repostatus.org/#active", +"description": "Active \u2013 The project has reached a stable, usable state and is being actively developed." +``` + +**(13)** +- Example: +``` +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/myproject/community) +[Reddit](https://www.reddit.com/r/myproject) +[Discord](https://discord.com/invite/xyz789) +``` +- Result: +``` +"value": "https://gitter.im/myproject/community" +.... +"value": "https://www.reddit.com/r/myproject" +..... +"value": "https://discord.com/invite/xyz789" +``` + + diff --git a/docs/readmefile.md b/docs/readmefile.md new file mode 100644 index 0000000..adad749 --- /dev/null +++ b/docs/readmefile.md @@ -0,0 +1,163 @@ +The following metadata fields can be extracted from a readme.md file. +Unlike others files formats (pom, cargo, cabal...), README documents do not follow a formal specification. They are free‑form text files, usually written in markdown or restructuredtext, and their structure varies widely across projects. SOMEF applies heuristics to identify common sections (e.g., Title, Description, Installation, Usage, License...) and extracts metadata accordingly. + +| Software metadata category | SOMEF metadata JSON path | README.MD metadata file field | +|--------------------------------|----------------------------------------|----------------------------------------| +| acknowledgement | acknowledgement[i].result.value | hearders with acknowledgement | +| citation | citation[i].result.value | headers with citation, reference, cite. Extract bibtext **(1)** | +| contact | contact[i].result.value | headers with contact | +| contributing_guidelines | contributing_guidelines[i].result.value | headers with contributing | +| contributors | contributors[i].result.value | headers with contributor | +| description | description[i].result.value | headers with description, introduction, basics, initiation, overview | +| documentation | documentation[i].result.value | github or gitlab url documentation **(2)**, headers with documentation, readthedocs same name project, readthedocs in badges, wiki links in badges and text | +| download | download[i].result.value | headers with download | +| executable_example | executable_example[i].result.value | extracts Binder from badgets **(3)** | +| faq | faq[i].result.value | headers with faq, errors, problems | +| full_title | full_title[i].result.value | extract full title **(4)** | +| homepage | homepage[i].result.value | homepage from badgets **(5)** | +| identifier | idenfier[i].result.value | extract from badgets directly or get from zenodo with latest doi **(6)**, swh identifiers **(7)** | +| images | images[i].result.value | other images in the README apart from the logo | +| installation | installation[i].result.value | headers with installation, install, setup, prepare, preparation, manual, guide | +| license | license[i].result.value | headers with license | +| logo | logo[i].result.value | look images in badges and text **(8)** | +| package_distribution | package_distribution[i].result.value | Pypi or latest Pypi version in badges **(9)** | +| related_documentation | dorelated_documentationumentation[i].result.value | readthedocs diferent name project | +| run | run[i].result.value | headers with run, execute | +| readme_url | readme_url[i].result.value | url in raw githubuser content **(10)** | +| related_papers | related_papers[i].result.value | look for arXiv reference in all the text **(11)** | +| repository_status | repository_status[i].result.value | badges with Project status **(12)** | +| requirements | requirements[i].result.value | headers with requirement, prerequisite, dependency, dependent | +| support | support[i].result.value | headers with support, help, report | +| support_channels | support_channels[i].result.value | extract information of gitter, reddit and discord in badges and text **(13)** | +| usage | usage[i].result.value | headers with usage, example, implement, implementation, demo, tutorial, start, started | + + +------ + +**(1)** +- Example: +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +- Result: +``` +{ + "result": { + "value": "@inproceedings{garijo2017widoco,\n url = {http://dgarijo.com/papers/widoco-iswc2017.pdf},\n funding = {USNSF ICER-1541029, NIH 1R01GM117097-01},\n doi = {10.1007/978-3-319-68204-4_9},\n organization = {Springer, Cham},\n year = {2017},\n pages = {94--102},\n booktitle = {International Semantic Web Conference},\n author = {Garijo, Daniel},\n title = {WIDOCO: a wizard for documenting ontologies},\n}", + "type": "Text_excerpt", + "format": "bibtex", + "doi": "10.1007/978-3-319-68204-4_9", + "title": "WIDOCO: a wizard for documenting ontologies", + "author": "Garijo, Daniel", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf" + }, +} +``` + + +**(2)** +- Example if github: +``` +f"https://github.com/{owner}/{repo_name}/tree/{urllib.parse.quote(repo_default_branch)}/{docs_path}" +``` +- Example if gitlab: +``` +f"https://{domain_gitlab}/{owner}/{repo_name}/-/tree/{urllib.parse.quote(repo_default_branch)}/{docs_path}" +``` + +**(3)** +- Example: `[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/user/repo/HEAD)` +- Result: `"value": "https://mybinder.org/v2/gh/user/repo/HEAD"` + +**(4)** +- Example: `# WIzard for DOCumenting Ontologies (WIDOCO)` +- Result: +``` +"full_title": [ + { + "result": { + "type": "String", + "value": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } +] +``` + +**(5)** +- Example: `[![Project homepage](https://img.shields.io/badge/homepage-project-blue)](https://myproject.org)` +- Result: `"value": "https://myproject.org"` + + +**(6)** +- Example: `[![DOI](https://zenodo.org/badge/11427075.svg)](https://doi.org/10.5281/zenodo.11093793)` +- Result: `"value": "https://doi.org/10.5281/zenodo.11093793"` + +**(7)** +- Example: `[![SWH](https://archive.softwareheritage.org/badge/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7/)](https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7;origin=...)` +- Result: ` "value": "https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7",` + + +**(8)** +- Example: `![Logo](src/main/resources/logo/logo2.png)` +- Result: `"value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png"`` + +**(9)** +- Example: `[![PyPI](https://badge.fury.io/py/somef.svg)](https://badge.fury.io/py/somef) ` +- Result: `"value": "https://pypi.org/project/somef"` + + +**(10)** +- Example: +``` +[Yulun Zhang](http://yulunzhang.com/), [Yapeng Tian](http://yapengtian.org/), [Yu Kong](http://www1.ece.neu.edu/~yukong/), [Bineng Zhong](https://scholar.google.de/citations?user=hvRBydsAAAAJ&hl=en), and [Yun Fu](http://www1.ece.neu.edu/~yunfu/), "Residual Dense Network for Image Super-Resolution", CVPR 2018 (spotlight), [[arXiv]](https://arxiv.org/abs/1802.08797) +``` +- Result: `"value": "https://arxiv.org/abs/1802.08797"` + + +**(11)** +- Example: +``` +f"https://raw.githubusercontent.com/{owner}/{repo_name}/{repo_ref}/{urllib.parse.quote(partial)}" +``` + +**(12)** +- Example: +``` + [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) +``` +- Result: +``` +"value": "https://www.repostatus.org/#active", +"description": "Active \u2013 The project has reached a stable, usable state and is being actively developed." +``` + +**(13)** +- Example: +``` +[![Gitter chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/myproject/community) +[Reddit](https://www.reddit.com/r/myproject) +[Discord](https://discord.com/invite/xyz789) +``` +- Result: +``` +"value": "https://gitter.im/myproject/community" +.... +"value": "https://www.reddit.com/r/myproject" +..... +"value": "https://discord.com/invite/xyz789" +``` + + diff --git a/docs/requirementstxt 2.md b/docs/requirementstxt 2.md new file mode 100644 index 0000000..591eabc --- /dev/null +++ b/docs/requirementstxt 2.md @@ -0,0 +1,26 @@ +The following metadata fields can be extracted from a requirements file. +These fields are defined in the [Requirements specification](https://pip.pypa.io/en/stable/reference/requirements-file-format/), currently at version **25.2**, and are mapped according to the [CodeMeta crosswalk for requirements files](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | REQUIREMENTS.TXT metadata file field | +|----------------------------------|------------------------------------|------------------------------------------| +| requirements - value | requirements[i].result.value | *(1)* | +| requirements - name | requirements[i].result.name | *(1)* | +| requirements - version | requirements[i].result.version| *(1)* | +| runtime_platform - value | runtime_platform[i].result.value | if Python *(1)* | +| runtime_platform - name | runtime_platform[i].result.name | "Python" | + + +--- + +*(1)* +- Example: `docstring_parser==0.7` +- Result: +``` +value : docstring_parser==0.7 +name : docstring_parser= +version : 0.7 +``` + +*(2)* +- Always "Python" and version if exists. +- Example: `python= ">=3.11"` \ No newline at end of file diff --git a/docs/requirementstxt.md b/docs/requirementstxt.md new file mode 100644 index 0000000..591eabc --- /dev/null +++ b/docs/requirementstxt.md @@ -0,0 +1,26 @@ +The following metadata fields can be extracted from a requirements file. +These fields are defined in the [Requirements specification](https://pip.pypa.io/en/stable/reference/requirements-file-format/), currently at version **25.2**, and are mapped according to the [CodeMeta crosswalk for requirements files](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | REQUIREMENTS.TXT metadata file field | +|----------------------------------|------------------------------------|------------------------------------------| +| requirements - value | requirements[i].result.value | *(1)* | +| requirements - name | requirements[i].result.name | *(1)* | +| requirements - version | requirements[i].result.version| *(1)* | +| runtime_platform - value | runtime_platform[i].result.value | if Python *(1)* | +| runtime_platform - name | runtime_platform[i].result.name | "Python" | + + +--- + +*(1)* +- Example: `docstring_parser==0.7` +- Result: +``` +value : docstring_parser==0.7 +name : docstring_parser= +version : 0.7 +``` + +*(2)* +- Always "Python" and version if exists. +- Example: `python= ">=3.11"` \ No newline at end of file diff --git a/docs/setuppy 2.md b/docs/setuppy 2.md new file mode 100644 index 0000000..6dbf8d7 --- /dev/null +++ b/docs/setuppy 2.md @@ -0,0 +1,35 @@ +The following metadata fields can be extracted from a setup.py file. +These fields are defined in the [Setup.py specification](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args), and are mapped according to the [CodeMeta crosswalk for python](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | SETUP.PY metadata file field | +|-------------------------------|------------------------------|------------------------------| +| authors - value | authors[i].result.value | author *(1)* | +| authors - email | authors[i].result.email | author_email or EMAIL *(1)* | +| code_repository | code_repository[i].result.value | url or URL | +| description | description[i].result .value | description or DESCRIPTION | +| keywords | keywords[i].result.value | keywords | +| license | license[i].result.value | license | +| package_id | package_id[i].result.value | name | +| programming_languages | programming_languages[i].result.value | if classifiers -> "python" *(2)* | + +--- + +*(1)* +- Example: +``` + author='Colin Raffel', + author_email='craffel@gmail.com', +``` +- Result: `result {'name': 'Colin Raffel', 'email':'craffel@gmail.com'}` + +*(2)* +- Example: +``` + classifiers=[ + "Development Status :: 3 - Alpha", + "Programming Language :: Python", + ], +``` +- Result: always `"value": "Python"` if 'Programming Language :: Python' in classifiers. + + diff --git a/docs/setuppy.md b/docs/setuppy.md new file mode 100644 index 0000000..6dbf8d7 --- /dev/null +++ b/docs/setuppy.md @@ -0,0 +1,35 @@ +The following metadata fields can be extracted from a setup.py file. +These fields are defined in the [Setup.py specification](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args), and are mapped according to the [CodeMeta crosswalk for python](https://github.com/codemeta/codemeta/blob/master/crosswalks/Python%20Distutils%20(PyPI).csv). + +| Software metadata category | SOMEF metadata JSON path | SETUP.PY metadata file field | +|-------------------------------|------------------------------|------------------------------| +| authors - value | authors[i].result.value | author *(1)* | +| authors - email | authors[i].result.email | author_email or EMAIL *(1)* | +| code_repository | code_repository[i].result.value | url or URL | +| description | description[i].result .value | description or DESCRIPTION | +| keywords | keywords[i].result.value | keywords | +| license | license[i].result.value | license | +| package_id | package_id[i].result.value | name | +| programming_languages | programming_languages[i].result.value | if classifiers -> "python" *(2)* | + +--- + +*(1)* +- Example: +``` + author='Colin Raffel', + author_email='craffel@gmail.com', +``` +- Result: `result {'name': 'Colin Raffel', 'email':'craffel@gmail.com'}` + +*(2)* +- Example: +``` + classifiers=[ + "Development Status :: 3 - Alpha", + "Programming Language :: Python", + ], +``` +- Result: always `"value": "Python"` if 'Programming Language :: Python' in classifiers. + + diff --git a/docs/supported_languages 2.md b/docs/supported_languages 2.md new file mode 100644 index 0000000..5b4b313 --- /dev/null +++ b/docs/supported_languages 2.md @@ -0,0 +1,33 @@ + +SOMEF recognizes the programming languages used in a software repository by inspecting +well-known configuration files, dependency descriptors and executable artifacts. +To know more about the extraction details for each type of file, click on it. + + + +| Language | Supported Files | +|-----------|----------------------------| +| Haskell | [`*.cabal`](./cabal.md) | +| Java | [`pom.xml`](./pom.md) | +| JavaScript | [`package.json`](./packagejson.md), [`bower.json`](./bower.md) | +| Julia | [`Project.toml`](./julia.md) | +| PHP | [`composer.json`](./composer.md) | +| Python | [`setup.py`](./setuppy.md), [`pyproject.toml`](./pyprojecttoml.md), [`requirements.txt`](./requirementstxt.md) | +| R | [`DESCRIPTION`](./description.md) | +| Ruby | [`*.gemspec`](./gemspec.md) | +| Rust | [`Cargo.toml`](./cargo.md) | + +--- + +SoMEF also detects the following files to recognize build instructions, workflows or executable examples: + + +| Language | Supported Files | Software metadata category | +|-----------|------------------------------------|-----------------------------| +| Docker | `Dockerfile`, `docker-compose.yml` | has_built_file +| Jupyter Notebook | `*.ipynb` | executable_example | +| Ontologies | `*.ttl`, `*.owl`, `*.nt`, `*.xml`, `*.jsonld` | ontologies | +| Shell | `*.sh` | has_script_file | +| YAML | `*.yml`, `*.yaml` | continuous_integration, workflows, publiccode | + + diff --git a/docs/supported_languages.md b/docs/supported_languages.md new file mode 100644 index 0000000..5b4b313 --- /dev/null +++ b/docs/supported_languages.md @@ -0,0 +1,33 @@ + +SOMEF recognizes the programming languages used in a software repository by inspecting +well-known configuration files, dependency descriptors and executable artifacts. +To know more about the extraction details for each type of file, click on it. + + + +| Language | Supported Files | +|-----------|----------------------------| +| Haskell | [`*.cabal`](./cabal.md) | +| Java | [`pom.xml`](./pom.md) | +| JavaScript | [`package.json`](./packagejson.md), [`bower.json`](./bower.md) | +| Julia | [`Project.toml`](./julia.md) | +| PHP | [`composer.json`](./composer.md) | +| Python | [`setup.py`](./setuppy.md), [`pyproject.toml`](./pyprojecttoml.md), [`requirements.txt`](./requirementstxt.md) | +| R | [`DESCRIPTION`](./description.md) | +| Ruby | [`*.gemspec`](./gemspec.md) | +| Rust | [`Cargo.toml`](./cargo.md) | + +--- + +SoMEF also detects the following files to recognize build instructions, workflows or executable examples: + + +| Language | Supported Files | Software metadata category | +|-----------|------------------------------------|-----------------------------| +| Docker | `Dockerfile`, `docker-compose.yml` | has_built_file +| Jupyter Notebook | `*.ipynb` | executable_example | +| Ontologies | `*.ttl`, `*.owl`, `*.nt`, `*.xml`, `*.jsonld` | ontologies | +| Shell | `*.sh` | has_script_file | +| YAML | `*.yml`, `*.yaml` | continuous_integration, workflows, publiccode | + + diff --git a/docs/supported_metadata_files 2.md b/docs/supported_metadata_files 2.md new file mode 100644 index 0000000..36c8700 --- /dev/null +++ b/docs/supported_metadata_files 2.md @@ -0,0 +1,112 @@ +# Supported Metadata Files + +This project supports extracting metadata from specific types of files commonly used to declare authorship and contribution in open source repositories. + + +## Supported Metadata Files in SOMEF + +SOMEF can extract metadata from a wide range of files commonly found in software repositories. Below is a list of supported file types, along with clickable examples from real projects: + +| File Name | Language | Description | Detail | Source Spec. | Version Spec.| Example | +|--------------------|----------------|-------------|--------|--------------|--------------|---------| +| `AUTHORS.md` | General | Lists contributors, authors, and affiliations relevant to the project |
[🔍](./author.md)
| [📄](https://opensource.google/documentation/reference/releasing/authors/)| |[Example](https://gist.github.com/juliengdt/91d80c812e41be891dcf) | +| `pom.xml` | Java / Maven | Project configuration file containing metadata and dependencies |
[🔍](./pom.md) | [📄](https://maven.apache.org/pom.html) | [4.0.0](https://maven.apache.org/xsd/maven-4.0.0.xsd) | [Example](https://github.com/apache/maven/blob/master/pom.xml) | +| `bower.json` | JavaScript (Bower) | Package descriptor used for configuring packages that can be used as a dependency for Bower-managed front-end projects. |
[🔍](./bower.md)
| [📄](https://github.com/bower/spec/blob/master/json.md)| |[Example](https://github.com/juanjemdIos/somef/blob/master/src/somef/test/test_data/repositories/js-template/bower.json) | +| `package.json` | JavaScript / Node.js | Defines metadata, scripts, and dependencies for Node.js projects |
[🔍](./packagejson.md)| [📄](https://docs.npmjs.com/cli/v10/configuring-npm/package-json)| 10.9.4|[Example](https://github.com/npm/cli/blob/latest/package.json) | +| `codemeta.json` | JSON-LD | Metadata file for research software using JSON-LD vocabulary |
[🔍](./codemetajson.md)
| [📄](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv)| [v3.0](https://w3id.org/codemeta/3.0)|[Example](https://github.com/codemeta/codemeta/blob/master/codemeta.json) | +| `readme.me` | Markdown | Main documentation file of repository |
[🔍](./readmefile.md)
| | |[Example](https://github.com/KnowledgeCaptureAndDiscovery/somef/blob/master/README.md) | +| `composer.json` | PHP | Manifest file serves as the package descriptor used in PHP projects. |
[🔍](./composer.md)
| [📄](https://getcomposer.org/doc/04-schema.md)| [2.8.12](https://getcomposer.org/changelog/2.8.12)|[Example](https://github.com/composer/composer/blob/main/composer.json) | +| `juliaProject.toml` | Python | Defines the package metadata and dependencies for Julia projects, used by the Pkg package manager.|
[🔍](./julia.md)
| [📄](https://docs.julialang.org/en/v1/)| |[Example](https://github.com/JuliaLang/TOML.jl/blob/master/Project.toml) | +| `pyproject.toml` | Python | Modern Python project configuration file used by tools like Poetry and Flit |
[🔍](./pyprojecttoml.md)
| [📄](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)| |[Example](https://github.com/KnowledgeCaptureAndDiscovery/somef/blob/master/pyproject.toml) | +| `requirements.txt` | Python | Lists Python package dependencies |
[🔍](./requirementstxt.md)
| [📄](https://pip.pypa.io/en/stable/reference/requirements-file-format/)| 25.2|[Example](https://github.com/oeg-upm/FAIR-Research-Object/blob/main/requirements.txt) | +| `setup.py` | Python | Package file format used in python projects |
[🔍](./setuppy.md)
| [📄](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args)| |[Example](https://github.com/oeg-upm/soca/blob/main/setup.py) | +| `DESCRIPTION` | R | Metadata file for R packages including title, author, and version |
[🔍](./description.md)
| [📄](https://r-pkgs.org/description.html)| | [Example](https://github.com/cran/ggplot2/blob/master/DESCRIPTION) | +| `*.gemspec` | Ruby | Manifest file serves as the package descriptor used in Ruby gem projects. |
[🔍](./gemspec.md)
| [📄](https://guides.rubygems.org/specification-reference/)| |[Example](https://github.com/rubygems/rubygems/blob/master/bundler/bundler.gemspec) | +| `cargo.toml` | Rust | Manifest file serves as the package descriptor used in Rust projects |
[🔍](./cargo.md)
| [📄](https://doc.rust-lang.org/cargo/reference/manifest.html)| |[Example](https://github.com/rust-lang/cargo/blob/master/Cargo.toml) | +| `*.cabal` | Haskell | Manifest file serving as the package descriptor for Haskell projects.|
[🔍](./cabal.md)
| [📄](https://cabal.readthedocs.io/en/3.10/cabal-package.html)| |[Example](https://github.com/haskell/cabal/blob/master/Cabal/Cabal.cabal) | +| `dockerfile` | Dockerfile | Build specification file for container images that can include software metadata via LABEL instructions (OCI specification).|
[🔍](./dockerfiledoc.md)
| [📄](https://docs.docker.com/reference/dockerfile/)| |[Example](https://github.com/FairwindsOps/nova/blob/master/Dockerfile) | +| `publiccode.yml` | YAML | YAML metadata file for public sector software projects|
[🔍](./publiccode.md)
| [📄](https://yml.publiccode.tools//)| |[Example](https://github.com/maykinmedia/objects-api/blob/master/publiccode.yaml) | + +> **Note:** The general principles behind metadata mapping in SOMEF are based on the [CodeMeta crosswalk](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv) and the [CodeMeta JSON-LD context](https://github.com/codemeta/codemeta/blob/master/codemeta.jsonld). +> However, each supported file type may have specific characteristics and field interpretations. + + + + +## Types of metadata in SOMEF + +| Type | Metadata Category | +|----------------------|---------------------------| +| Agent | authors | +| Keywords | keywords | +| License | license | +| Release | version | +| Software_application | requirements | +| String | description | +| String | name | +| String | package_id | +| String | runtime_platform | +| Url | has_package_file | +| Url | homepage | +| Url | issue_tracker | +| Url | package_distribution | + + +## Example: Dependency Metadata Extraction from Configuration Files + +SOMEF parses configuration files like `pom.xml` to extract **structured metadata** about software dependencies and other requirements. + +--- + +### Source File: Snippet from `Widoco/pom.xml` + +Below is the XML fragment for the Maven dependency that is being parsed: + +```xml + + + org.apache.maven + maven-model + 3.9.0 + + +``` + + +The following Python code snippet show the logic used by the SOMEF parser to transform the XML elements to the JSON metadata structure: + +``` + if project_data["dependencies"]: + for dependency in project_data["dependencies"]: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": f'{dependency.get("groupId", "")}.{dependency.get("artifactId", "")}'.strip("."), + "name": dependency.get("artifactId", ""), + "version": dependency.get("version", ""), + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) +``` + + +After applying the mapping logic, the metadata for the dependency is stored under the requirements category (CAT_REQUIREMENTS in this case) with the following JSON structure: + +``` somef json + + "requirements": [ + { + "result": { + "value": "org.apache.maven.maven-model", + "name": "maven-model", + "version": "3.9.0", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, +``` diff --git a/docs/supported_metadata_files.md b/docs/supported_metadata_files.md new file mode 100644 index 0000000..36c8700 --- /dev/null +++ b/docs/supported_metadata_files.md @@ -0,0 +1,112 @@ +# Supported Metadata Files + +This project supports extracting metadata from specific types of files commonly used to declare authorship and contribution in open source repositories. + + +## Supported Metadata Files in SOMEF + +SOMEF can extract metadata from a wide range of files commonly found in software repositories. Below is a list of supported file types, along with clickable examples from real projects: + +| File Name | Language | Description | Detail | Source Spec. | Version Spec.| Example | +|--------------------|----------------|-------------|--------|--------------|--------------|---------| +| `AUTHORS.md` | General | Lists contributors, authors, and affiliations relevant to the project |
[🔍](./author.md)
| [📄](https://opensource.google/documentation/reference/releasing/authors/)| |[Example](https://gist.github.com/juliengdt/91d80c812e41be891dcf) | +| `pom.xml` | Java / Maven | Project configuration file containing metadata and dependencies |
[🔍](./pom.md) | [📄](https://maven.apache.org/pom.html) | [4.0.0](https://maven.apache.org/xsd/maven-4.0.0.xsd) | [Example](https://github.com/apache/maven/blob/master/pom.xml) | +| `bower.json` | JavaScript (Bower) | Package descriptor used for configuring packages that can be used as a dependency for Bower-managed front-end projects. |
[🔍](./bower.md)
| [📄](https://github.com/bower/spec/blob/master/json.md)| |[Example](https://github.com/juanjemdIos/somef/blob/master/src/somef/test/test_data/repositories/js-template/bower.json) | +| `package.json` | JavaScript / Node.js | Defines metadata, scripts, and dependencies for Node.js projects |
[🔍](./packagejson.md)| [📄](https://docs.npmjs.com/cli/v10/configuring-npm/package-json)| 10.9.4|[Example](https://github.com/npm/cli/blob/latest/package.json) | +| `codemeta.json` | JSON-LD | Metadata file for research software using JSON-LD vocabulary |
[🔍](./codemetajson.md)
| [📄](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv)| [v3.0](https://w3id.org/codemeta/3.0)|[Example](https://github.com/codemeta/codemeta/blob/master/codemeta.json) | +| `readme.me` | Markdown | Main documentation file of repository |
[🔍](./readmefile.md)
| | |[Example](https://github.com/KnowledgeCaptureAndDiscovery/somef/blob/master/README.md) | +| `composer.json` | PHP | Manifest file serves as the package descriptor used in PHP projects. |
[🔍](./composer.md)
| [📄](https://getcomposer.org/doc/04-schema.md)| [2.8.12](https://getcomposer.org/changelog/2.8.12)|[Example](https://github.com/composer/composer/blob/main/composer.json) | +| `juliaProject.toml` | Python | Defines the package metadata and dependencies for Julia projects, used by the Pkg package manager.|
[🔍](./julia.md)
| [📄](https://docs.julialang.org/en/v1/)| |[Example](https://github.com/JuliaLang/TOML.jl/blob/master/Project.toml) | +| `pyproject.toml` | Python | Modern Python project configuration file used by tools like Poetry and Flit |
[🔍](./pyprojecttoml.md)
| [📄](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)| |[Example](https://github.com/KnowledgeCaptureAndDiscovery/somef/blob/master/pyproject.toml) | +| `requirements.txt` | Python | Lists Python package dependencies |
[🔍](./requirementstxt.md)
| [📄](https://pip.pypa.io/en/stable/reference/requirements-file-format/)| 25.2|[Example](https://github.com/oeg-upm/FAIR-Research-Object/blob/main/requirements.txt) | +| `setup.py` | Python | Package file format used in python projects |
[🔍](./setuppy.md)
| [📄](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args)| |[Example](https://github.com/oeg-upm/soca/blob/main/setup.py) | +| `DESCRIPTION` | R | Metadata file for R packages including title, author, and version |
[🔍](./description.md)
| [📄](https://r-pkgs.org/description.html)| | [Example](https://github.com/cran/ggplot2/blob/master/DESCRIPTION) | +| `*.gemspec` | Ruby | Manifest file serves as the package descriptor used in Ruby gem projects. |
[🔍](./gemspec.md)
| [📄](https://guides.rubygems.org/specification-reference/)| |[Example](https://github.com/rubygems/rubygems/blob/master/bundler/bundler.gemspec) | +| `cargo.toml` | Rust | Manifest file serves as the package descriptor used in Rust projects |
[🔍](./cargo.md)
| [📄](https://doc.rust-lang.org/cargo/reference/manifest.html)| |[Example](https://github.com/rust-lang/cargo/blob/master/Cargo.toml) | +| `*.cabal` | Haskell | Manifest file serving as the package descriptor for Haskell projects.|
[🔍](./cabal.md)
| [📄](https://cabal.readthedocs.io/en/3.10/cabal-package.html)| |[Example](https://github.com/haskell/cabal/blob/master/Cabal/Cabal.cabal) | +| `dockerfile` | Dockerfile | Build specification file for container images that can include software metadata via LABEL instructions (OCI specification).|
[🔍](./dockerfiledoc.md)
| [📄](https://docs.docker.com/reference/dockerfile/)| |[Example](https://github.com/FairwindsOps/nova/blob/master/Dockerfile) | +| `publiccode.yml` | YAML | YAML metadata file for public sector software projects|
[🔍](./publiccode.md)
| [📄](https://yml.publiccode.tools//)| |[Example](https://github.com/maykinmedia/objects-api/blob/master/publiccode.yaml) | + +> **Note:** The general principles behind metadata mapping in SOMEF are based on the [CodeMeta crosswalk](https://github.com/codemeta/codemeta/blob/master/crosswalk.csv) and the [CodeMeta JSON-LD context](https://github.com/codemeta/codemeta/blob/master/codemeta.jsonld). +> However, each supported file type may have specific characteristics and field interpretations. + + + + +## Types of metadata in SOMEF + +| Type | Metadata Category | +|----------------------|---------------------------| +| Agent | authors | +| Keywords | keywords | +| License | license | +| Release | version | +| Software_application | requirements | +| String | description | +| String | name | +| String | package_id | +| String | runtime_platform | +| Url | has_package_file | +| Url | homepage | +| Url | issue_tracker | +| Url | package_distribution | + + +## Example: Dependency Metadata Extraction from Configuration Files + +SOMEF parses configuration files like `pom.xml` to extract **structured metadata** about software dependencies and other requirements. + +--- + +### Source File: Snippet from `Widoco/pom.xml` + +Below is the XML fragment for the Maven dependency that is being parsed: + +```xml + + + org.apache.maven + maven-model + 3.9.0 + + +``` + + +The following Python code snippet show the logic used by the SOMEF parser to transform the XML elements to the JSON metadata structure: + +``` + if project_data["dependencies"]: + for dependency in project_data["dependencies"]: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": f'{dependency.get("groupId", "")}.{dependency.get("artifactId", "")}'.strip("."), + "name": dependency.get("artifactId", ""), + "version": dependency.get("version", ""), + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) +``` + + +After applying the mapping logic, the metadata for the dependency is stored under the requirements category (CAT_REQUIREMENTS in this case) with the following JSON structure: + +``` somef json + + "requirements": [ + { + "result": { + "value": "org.apache.maven.maven-model", + "name": "maven-model", + "version": "3.9.0", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, +``` diff --git a/docs/usage.md b/docs/usage.md index 7b51d73..89f3102 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,4 +1,4 @@ -To see the available options for SOMEF-core: +To see the available options for SOMEF: ```bash somef_core --help @@ -52,7 +52,7 @@ Options: file. -m, --missing JSON report with the missing metadata fields - SOMEF-core was not able to find. The report will + SOMEF was not able to find. The report will be placed in $PATH_missing.json, where $PATH is -o, -c or -g. -kt, --keep_tmp PATH SOMEF will NOT delete the temporary folder diff --git a/mkdocs.yml b/mkdocs.yml index e3e2801..6000586 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,6 +4,23 @@ nav: - Install: install.md - Usage: usage.md - Output: output.md + - Supported metadata files: supported_metadata_files.md + - Supported languages: supported_languages.md + # - Authors: author.md + # - Bower: bower.md + # - Cabal: cabal.md + # - Cargo: cargo.md + # - Codemeta: codemetajson.md + # - Composer: composer.md + # - Description: description.md + # - Gemespec: gemspec.md + # - Julia Projects: julia.md + # - Package JSON: packagejson.md + # - Pom: pom.md + # - Pyproject: pyprojecttoml.md + # - Requirements: requirementstxt.md + # - Setup: setuppy.md + theme: name: material diff --git a/output 2.json-ld b/output 2.json-ld new file mode 100644 index 0000000..1944e63 --- /dev/null +++ b/output 2.json-ld @@ -0,0 +1,263 @@ +@prefix ns1: . +@prefix ns2: . +@prefix xsd: . + + a ns2:Person ; + ns2:name "tpronk" . + + a ns2:CreativeWork ; + ns1:name "GNU Affero General Public License v3.0" ; + ns1:url "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/LICENSE"^^xsd:anyURI . + + a ns1:Software ; + ns2:license ; + ns1:contactDetails """Contact person responsible for maintaining a software component +""" ; + ns1:contributingGuidelines """These guidelines were copied from [PychoPy](https://github.com/psychopy/psychopy/edit/dev/CONTRIBUTING.md) + +# Have you ever contributed to an Open Source project? +Your first contribution can be a bit intimidating, but feel free to give it a try. If you get stuck, don't hesitate to ask for help in our [developer forum](https://discourse.psychopy.org/c/dev). This is also a good place to pitch your idea. Next up: +* **I won't program it myself.** Please file a [GitHub issue](https://github.com/psychopy/psychopy/issues). +* **I'd like to take a shot.** Read on to find out how! + +# How to contribute +Contributing to PsychoPy consists of four steps: +1. Getting your own copy +2. Making your changes +3. Committing your changes +4. Submitting a Pull Request + +## 1. Getting your own copy of the PsychoPy codebase +To be sure your improvements can easily be integrated, follow these steps: +1. **Make a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of the [PsychoPy repo](https://github.com/psychopy/psychopy).** This provides you with your own copy of the PsychoPy source code. +2. **Inside your fork, make a new [branch](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches) for the feature you've got in mind.** If you'd like to fix a bug, base your new branch on the *release* branch. If you'd like to add a new feature, base it on the *dev* branch. We tend to name branches after the feature we're building. For example `olfactory_component`. +3. **Clone your fork to your hard drive.** Next, switch to the new branch and you're all set up! + +Look [here](https://www.psychopy.org/developers/repository.html) to see how the PsychoPy repo is organized. + +## 2. Making your changes +To help you get started with modifying PsychoPy, we've got some [developer guides](https://www.psychopy.org/developers/index.html). To try out your modified PsychoPy, do a [developer's install](https://www.psychopy.org/download.html#developers-install). + +## 3. Committing your changes +Once you're happy with your changes, commit them to your GitHub repo. Please use the tags below in your commit and add an informative message. + - **BF:** bug fix. For fixing bugs in the *release* branch. + - **FF:** ‘feature’ fix. For fixing bugs in the *dev* branch. + - **RF:** refactoring + - **NF:** new feature + - **ENH:** enhancement (to existing code, but don't worry too much about the difference between this and NF) + - **DOC:** for all kinds of documentation related commits + - **TEST:** for adding or changing tests + +## 4. File a Pull Request +Once you're done, it's time to add it to the central PsychoPy source code. File a [Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from your own fork and branch to the PsychoPy repo. Be sure to target the right branch in PsychoPy (*release* or *dev*). Thanks for contributing! +""" ; + ns1:contributionInstructions """These guidelines were copied from [PychoPy](https://github.com/psychopy/psychopy/edit/dev/CONTRIBUTING.md) + +# Have you ever contributed to an Open Source project? +Your first contribution can be a bit intimidating, but feel free to give it a try. If you get stuck, don't hesitate to ask for help in our [developer forum](https://discourse.psychopy.org/c/dev). This is also a good place to pitch your idea. Next up: +* **I won't program it myself.** Please file a [GitHub issue](https://github.com/psychopy/psychopy/issues). +* **I'd like to take a shot.** Read on to find out how! + +# How to contribute +Contributing to PsychoPy consists of four steps: +1. Getting your own copy +2. Making your changes +3. Committing your changes +4. Submitting a Pull Request + +## 1. Getting your own copy of the PsychoPy codebase +To be sure your improvements can easily be integrated, follow these steps: +1. **Make a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of the [PsychoPy repo](https://github.com/psychopy/psychopy).** This provides you with your own copy of the PsychoPy source code. +2. **Inside your fork, make a new [branch](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches) for the feature you've got in mind.** If you'd like to fix a bug, base your new branch on the *release* branch. If you'd like to add a new feature, base it on the *dev* branch. We tend to name branches after the feature we're building. For example `olfactory_component`. +3. **Clone your fork to your hard drive.** Next, switch to the new branch and you're all set up! + +Look [here](https://www.psychopy.org/developers/repository.html) to see how the PsychoPy repo is organized. + +## 2. Making your changes +To help you get started with modifying PsychoPy, we've got some [developer guides](https://www.psychopy.org/developers/index.html). To try out your modified PsychoPy, do a [developer's install](https://www.psychopy.org/download.html#developers-install). + +## 3. Committing your changes +Once you're happy with your changes, commit them to your GitHub repo. Please use the tags below in your commit and add an informative message. + - **BF:** bug fix. For fixing bugs in the *release* branch. + - **FF:** ‘feature’ fix. For fixing bugs in the *dev* branch. + - **RF:** refactoring + - **NF:** new feature + - **ENH:** enhancement (to existing code, but don't worry too much about the difference between this and NF) + - **DOC:** for all kinds of documentation related commits + - **TEST:** for adding or changing tests + +## 4. File a Pull Request +Once you're done, it's time to add it to the central PsychoPy source code. File a [Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from your own fork and branch to the PsychoPy repo. Be sure to target the right branch in PsychoPy (*release* or *dev*). Thanks for contributing! +"""^^xsd:anyURI ; + ns1:dateCreated "2023-11-28T12:30:28+00:00"^^xsd:dateTime ; + ns1:dateModified "2023-12-12T15:35:54+00:00"^^xsd:dateTime ; + ns1:description "This repo aims to provide values for each metadata field that SOMEF (v0.9.4) can extract" ; + ns1:hasAcknowledgments """This demonstration repo was created during the maSMP hackathon at [ZB MED](https://www.zbmed.de/en) sponsored by [NFDI4DataScience](https://www.nfdi4datascience.de). NFDI4DataScience is a consortium funded by the German Research Foundation (DFG), project number 460234259. +""" ; + ns1:hasBuildFile "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/Dockerfile"^^xsd:anyURI ; + ns1:hasCodeOfConduct """# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. +""" ; + ns1:hasDownloadUrl "https://github.com/tpronk/somef-demo-repo/releases"^^xsd:anyURI ; + ns1:hasExample "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/executable_example.ipynb"^^xsd:anyURI ; + ns1:hasExecutableInstructions """There is no code in this repo that can be run. +""" ; + ns1:hasExecutableNotebook "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/executable_example.ipynb" ; + ns1:hasFAQ """Frequently asked questions about a software component +""" ; + ns1:hasInstallationInstructions """##Installation instructions +A set of instructions that indicate how to install a target repository +""" ; + ns1:hasLongName "somef-demo-repo" ; + ns1:hasSourceCode ; + ns1:hasSupportScriptLocation "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/script_file.sh"^^xsd:anyURI ; + ns1:hasUsageNotes """##Usage examples +Assumptions and considerations recorded by the authors when executing a software component, or examples on how to use it. +""" ; + ns1:hasVersion ; + ns1:identifier "https://zenodo.org/badge/latestdoi/450496579"^^xsd:anyURI ; + ns1:issueTracker "https://api.github.com/repos/tpronk/somef-demo-repo/issues"^^xsd:anyURI ; + ns1:keywords "topic1, topic2, topic3" ; + ns1:name "tpronk/somef-demo-repo" ; + ns1:readme "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/README.md"^^xsd:anyURI ; + ns1:softwareRequirements """Pre-requisites and dependencies needed to execute a software component. +""" ; + ns1:supportDetails """Guidelines and links of where to obtain support for a software component +""", + """[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/OpenGeoscience/geonotebook) +""" . + + a ns2:SoftwareSourceCode ; + ns1:codeRepository "https://github.com/tpronk/somef-demo-repo"^^xsd:anyURI ; + ns1:name "tpronk/somef-demo-repo" ; + ns1:programmingLanguage "Common Workflow Language", + "Dockerfile", + "Jupyter Notebook", + "Shell" . + diff --git a/output.json-ld b/output.json-ld new file mode 100644 index 0000000..1944e63 --- /dev/null +++ b/output.json-ld @@ -0,0 +1,263 @@ +@prefix ns1: . +@prefix ns2: . +@prefix xsd: . + + a ns2:Person ; + ns2:name "tpronk" . + + a ns2:CreativeWork ; + ns1:name "GNU Affero General Public License v3.0" ; + ns1:url "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/LICENSE"^^xsd:anyURI . + + a ns1:Software ; + ns2:license ; + ns1:contactDetails """Contact person responsible for maintaining a software component +""" ; + ns1:contributingGuidelines """These guidelines were copied from [PychoPy](https://github.com/psychopy/psychopy/edit/dev/CONTRIBUTING.md) + +# Have you ever contributed to an Open Source project? +Your first contribution can be a bit intimidating, but feel free to give it a try. If you get stuck, don't hesitate to ask for help in our [developer forum](https://discourse.psychopy.org/c/dev). This is also a good place to pitch your idea. Next up: +* **I won't program it myself.** Please file a [GitHub issue](https://github.com/psychopy/psychopy/issues). +* **I'd like to take a shot.** Read on to find out how! + +# How to contribute +Contributing to PsychoPy consists of four steps: +1. Getting your own copy +2. Making your changes +3. Committing your changes +4. Submitting a Pull Request + +## 1. Getting your own copy of the PsychoPy codebase +To be sure your improvements can easily be integrated, follow these steps: +1. **Make a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of the [PsychoPy repo](https://github.com/psychopy/psychopy).** This provides you with your own copy of the PsychoPy source code. +2. **Inside your fork, make a new [branch](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches) for the feature you've got in mind.** If you'd like to fix a bug, base your new branch on the *release* branch. If you'd like to add a new feature, base it on the *dev* branch. We tend to name branches after the feature we're building. For example `olfactory_component`. +3. **Clone your fork to your hard drive.** Next, switch to the new branch and you're all set up! + +Look [here](https://www.psychopy.org/developers/repository.html) to see how the PsychoPy repo is organized. + +## 2. Making your changes +To help you get started with modifying PsychoPy, we've got some [developer guides](https://www.psychopy.org/developers/index.html). To try out your modified PsychoPy, do a [developer's install](https://www.psychopy.org/download.html#developers-install). + +## 3. Committing your changes +Once you're happy with your changes, commit them to your GitHub repo. Please use the tags below in your commit and add an informative message. + - **BF:** bug fix. For fixing bugs in the *release* branch. + - **FF:** ‘feature’ fix. For fixing bugs in the *dev* branch. + - **RF:** refactoring + - **NF:** new feature + - **ENH:** enhancement (to existing code, but don't worry too much about the difference between this and NF) + - **DOC:** for all kinds of documentation related commits + - **TEST:** for adding or changing tests + +## 4. File a Pull Request +Once you're done, it's time to add it to the central PsychoPy source code. File a [Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from your own fork and branch to the PsychoPy repo. Be sure to target the right branch in PsychoPy (*release* or *dev*). Thanks for contributing! +""" ; + ns1:contributionInstructions """These guidelines were copied from [PychoPy](https://github.com/psychopy/psychopy/edit/dev/CONTRIBUTING.md) + +# Have you ever contributed to an Open Source project? +Your first contribution can be a bit intimidating, but feel free to give it a try. If you get stuck, don't hesitate to ask for help in our [developer forum](https://discourse.psychopy.org/c/dev). This is also a good place to pitch your idea. Next up: +* **I won't program it myself.** Please file a [GitHub issue](https://github.com/psychopy/psychopy/issues). +* **I'd like to take a shot.** Read on to find out how! + +# How to contribute +Contributing to PsychoPy consists of four steps: +1. Getting your own copy +2. Making your changes +3. Committing your changes +4. Submitting a Pull Request + +## 1. Getting your own copy of the PsychoPy codebase +To be sure your improvements can easily be integrated, follow these steps: +1. **Make a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of the [PsychoPy repo](https://github.com/psychopy/psychopy).** This provides you with your own copy of the PsychoPy source code. +2. **Inside your fork, make a new [branch](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches) for the feature you've got in mind.** If you'd like to fix a bug, base your new branch on the *release* branch. If you'd like to add a new feature, base it on the *dev* branch. We tend to name branches after the feature we're building. For example `olfactory_component`. +3. **Clone your fork to your hard drive.** Next, switch to the new branch and you're all set up! + +Look [here](https://www.psychopy.org/developers/repository.html) to see how the PsychoPy repo is organized. + +## 2. Making your changes +To help you get started with modifying PsychoPy, we've got some [developer guides](https://www.psychopy.org/developers/index.html). To try out your modified PsychoPy, do a [developer's install](https://www.psychopy.org/download.html#developers-install). + +## 3. Committing your changes +Once you're happy with your changes, commit them to your GitHub repo. Please use the tags below in your commit and add an informative message. + - **BF:** bug fix. For fixing bugs in the *release* branch. + - **FF:** ‘feature’ fix. For fixing bugs in the *dev* branch. + - **RF:** refactoring + - **NF:** new feature + - **ENH:** enhancement (to existing code, but don't worry too much about the difference between this and NF) + - **DOC:** for all kinds of documentation related commits + - **TEST:** for adding or changing tests + +## 4. File a Pull Request +Once you're done, it's time to add it to the central PsychoPy source code. File a [Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from your own fork and branch to the PsychoPy repo. Be sure to target the right branch in PsychoPy (*release* or *dev*). Thanks for contributing! +"""^^xsd:anyURI ; + ns1:dateCreated "2023-11-28T12:30:28+00:00"^^xsd:dateTime ; + ns1:dateModified "2023-12-12T15:35:54+00:00"^^xsd:dateTime ; + ns1:description "This repo aims to provide values for each metadata field that SOMEF (v0.9.4) can extract" ; + ns1:hasAcknowledgments """This demonstration repo was created during the maSMP hackathon at [ZB MED](https://www.zbmed.de/en) sponsored by [NFDI4DataScience](https://www.nfdi4datascience.de). NFDI4DataScience is a consortium funded by the German Research Foundation (DFG), project number 460234259. +""" ; + ns1:hasBuildFile "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/Dockerfile"^^xsd:anyURI ; + ns1:hasCodeOfConduct """# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. +""" ; + ns1:hasDownloadUrl "https://github.com/tpronk/somef-demo-repo/releases"^^xsd:anyURI ; + ns1:hasExample "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/executable_example.ipynb"^^xsd:anyURI ; + ns1:hasExecutableInstructions """There is no code in this repo that can be run. +""" ; + ns1:hasExecutableNotebook "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/executable_example.ipynb" ; + ns1:hasFAQ """Frequently asked questions about a software component +""" ; + ns1:hasInstallationInstructions """##Installation instructions +A set of instructions that indicate how to install a target repository +""" ; + ns1:hasLongName "somef-demo-repo" ; + ns1:hasSourceCode ; + ns1:hasSupportScriptLocation "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/script_file.sh"^^xsd:anyURI ; + ns1:hasUsageNotes """##Usage examples +Assumptions and considerations recorded by the authors when executing a software component, or examples on how to use it. +""" ; + ns1:hasVersion ; + ns1:identifier "https://zenodo.org/badge/latestdoi/450496579"^^xsd:anyURI ; + ns1:issueTracker "https://api.github.com/repos/tpronk/somef-demo-repo/issues"^^xsd:anyURI ; + ns1:keywords "topic1, topic2, topic3" ; + ns1:name "tpronk/somef-demo-repo" ; + ns1:readme "https://raw.githubusercontent.com/tpronk/somef-demo-repo/main/README.md"^^xsd:anyURI ; + ns1:softwareRequirements """Pre-requisites and dependencies needed to execute a software component. +""" ; + ns1:supportDetails """Guidelines and links of where to obtain support for a software component +""", + """[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/OpenGeoscience/geonotebook) +""" . + + a ns2:SoftwareSourceCode ; + ns1:codeRepository "https://github.com/tpronk/somef-demo-repo"^^xsd:anyURI ; + ns1:name "tpronk/somef-demo-repo" ; + ns1:programmingLanguage "Common Workflow Language", + "Dockerfile", + "Jupyter Notebook", + "Shell" . + diff --git a/poetry.lock b/poetry.lock index 9bdb2f2..aa17c3d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,46 +2,38 @@ [[package]] name = "anyascii" -version = "0.3.2" +version = "0.3.3" description = "Unicode to ASCII transliteration" optional = false python-versions = ">=3.3" groups = ["main"] files = [ - {file = "anyascii-0.3.2-py3-none-any.whl", hash = "sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4"}, - {file = "anyascii-0.3.2.tar.gz", hash = "sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730"}, + {file = "anyascii-0.3.3-py3-none-any.whl", hash = "sha256:f5ab5e53c8781a36b5a40e1296a0eeda2f48c649ef10c3921c1381b1d00dee7a"}, + {file = "anyascii-0.3.3.tar.gz", hash = "sha256:c94e9dd9d47b3d9494eca305fef9447d00b4bf1a32aff85aa746fa3ec7fb95c3"}, ] [[package]] name = "attrs" -version = "25.3.0" +version = "25.4.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, + {file = "attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373"}, + {file = "attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11"}, ] -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - [[package]] name = "beautifulsoup4" -version = "4.13.4" +version = "4.14.2" description = "Screen-scraping library" optional = false python-versions = ">=3.7.0" groups = ["main"] files = [ - {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, - {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, + {file = "beautifulsoup4-4.14.2-py3-none-any.whl", hash = "sha256:5ef6fa3a8cbece8488d66985560f97ed091e22bbc4e9c2338508a9d5de6d4515"}, + {file = "beautifulsoup4-4.14.2.tar.gz", hash = "sha256:2a98ab9f944a11acee9cc848508ec28d9228abfd522ef0fad6a02a72e0ded69e"}, ] [package.dependencies] @@ -85,14 +77,14 @@ beautifulsoup4 = "*" [[package]] name = "certifi" -version = "2025.6.15" +version = "2025.10.5" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"}, - {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"}, + {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"}, + {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, ] [[package]] @@ -109,104 +101,91 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.4.2" +version = "3.4.3" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a"}, - {file = "charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a"}, - {file = "charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c"}, - {file = "charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7"}, - {file = "charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win32.whl", hash = "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58"}, - {file = "charset_normalizer-3.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win32.whl", hash = "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7"}, - {file = "charset_normalizer-3.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win32.whl", hash = "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471"}, - {file = "charset_normalizer-3.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e"}, - {file = "charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0"}, - {file = "charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, + {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, + {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, ] [[package]] @@ -226,14 +205,14 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "click-option-group" -version = "0.5.7" +version = "0.5.8" description = "Option groups missing in Click" optional = false python-versions = ">=3.7" groups = ["main"] files = [ - {file = "click_option_group-0.5.7-py3-none-any.whl", hash = "sha256:96b9f52f397ef4d916f81929bd6c1f85e89046c7a401a64e72a61ae74ad35c24"}, - {file = "click_option_group-0.5.7.tar.gz", hash = "sha256:8dc780be038712fc12c9fecb3db4fe49e0d0723f9c171d7cda85c20369be693c"}, + {file = "click_option_group-0.5.8-py3-none-any.whl", hash = "sha256:959065a45ccf58fcc48ec22f18fb50c1e59494612f0a1c13c4e714554434b502"}, + {file = "click_option_group-0.5.8.tar.gz", hash = "sha256:7dc8d534a066382be748b20dd65270e59e0393bc765a7744df86b059d4e00e62"}, ] [package.dependencies] @@ -265,6 +244,7 @@ description = "Python library for calculating contours of 2D quadrilateral grids optional = false python-versions = ">=3.9" groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7"}, {file = "contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42"}, @@ -343,6 +323,99 @@ mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pil test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] +[[package]] +name = "contourpy" +version = "1.3.3" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.11" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "contourpy-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:709a48ef9a690e1343202916450bc48b9e51c049b089c7f79a267b46cffcdaa1"}, + {file = "contourpy-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:23416f38bfd74d5d28ab8429cc4d63fa67d5068bd711a85edb1c3fb0c3e2f381"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:929ddf8c4c7f348e4c0a5a3a714b5c8542ffaa8c22954862a46ca1813b667ee7"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9e999574eddae35f1312c2b4b717b7885d4edd6cb46700e04f7f02db454e67c1"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0bf67e0e3f482cb69779dd3061b534eb35ac9b17f163d851e2a547d56dba0a3a"}, + {file = "contourpy-1.3.3-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:51e79c1f7470158e838808d4a996fa9bac72c498e93d8ebe5119bc1e6becb0db"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:598c3aaece21c503615fd59c92a3598b428b2f01bfb4b8ca9c4edeecc2438620"}, + {file = "contourpy-1.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:322ab1c99b008dad206d406bb61d014cf0174df491ae9d9d0fac6a6fda4f977f"}, + {file = "contourpy-1.3.3-cp311-cp311-win32.whl", hash = "sha256:fd907ae12cd483cd83e414b12941c632a969171bf90fc937d0c9f268a31cafff"}, + {file = "contourpy-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:3519428f6be58431c56581f1694ba8e50626f2dd550af225f82fb5f5814d2a42"}, + {file = "contourpy-1.3.3-cp311-cp311-win_arm64.whl", hash = "sha256:15ff10bfada4bf92ec8b31c62bf7c1834c244019b4a33095a68000d7075df470"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b08a32ea2f8e42cf1d4be3169a98dd4be32bafe4f22b6c4cb4ba810fa9e5d2cb"}, + {file = "contourpy-1.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:556dba8fb6f5d8742f2923fe9457dbdd51e1049c4a43fd3986a0b14a1d815fc6"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92d9abc807cf7d0e047b95ca5d957cf4792fcd04e920ca70d48add15c1a90ea7"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2e8faa0ed68cb29af51edd8e24798bb661eac3bd9f65420c1887b6ca89987c8"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:626d60935cf668e70a5ce6ff184fd713e9683fb458898e4249b63be9e28286ea"}, + {file = "contourpy-1.3.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4d00e655fcef08aba35ec9610536bfe90267d7ab5ba944f7032549c55a146da1"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:451e71b5a7d597379ef572de31eeb909a87246974d960049a9848c3bc6c41bf7"}, + {file = "contourpy-1.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:459c1f020cd59fcfe6650180678a9993932d80d44ccde1fa1868977438f0b411"}, + {file = "contourpy-1.3.3-cp312-cp312-win32.whl", hash = "sha256:023b44101dfe49d7d53932be418477dba359649246075c996866106da069af69"}, + {file = "contourpy-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:8153b8bfc11e1e4d75bcb0bff1db232f9e10b274e0929de9d608027e0d34ff8b"}, + {file = "contourpy-1.3.3-cp312-cp312-win_arm64.whl", hash = "sha256:07ce5ed73ecdc4a03ffe3e1b3e3c1166db35ae7584be76f65dbbe28a7791b0cc"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5"}, + {file = "contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67"}, + {file = "contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659"}, + {file = "contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7"}, + {file = "contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d"}, + {file = "contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263"}, + {file = "contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d"}, + {file = "contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99"}, + {file = "contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a"}, + {file = "contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e"}, + {file = "contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8"}, + {file = "contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a"}, + {file = "contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36"}, + {file = "contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b"}, + {file = "contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36"}, + {file = "contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d"}, + {file = "contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd"}, + {file = "contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772"}, + {file = "contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f"}, + {file = "contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4"}, + {file = "contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f"}, + {file = "contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc"}, + {file = "contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ed3657edf08512fc3fe81b510e35c2012fbd3081d2e26160f27ca28affec989"}, + {file = "contourpy-1.3.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:3d1a3799d62d45c18bafd41c5fa05120b96a28079f2393af559b843d1a966a77"}, + {file = "contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880"}, +] + +[package.dependencies] +numpy = ">=1.25" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["bokeh", "contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.17.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] + [[package]] name = "contractions" version = "0.1.73" @@ -394,14 +467,14 @@ test = ["pytest (>=6)"] [[package]] name = "fastjsonschema" -version = "2.21.1" +version = "2.21.2" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" groups = ["main"] files = [ - {file = "fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667"}, - {file = "fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4"}, + {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"}, + {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"}, ] [package.extras] @@ -409,58 +482,74 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "fonttools" -version = "4.58.4" +version = "4.60.1" description = "Tools to manipulate font files" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "fonttools-4.58.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:834542f13fee7625ad753b2db035edb674b07522fcbdd0ed9e9a9e2a1034467f"}, - {file = "fonttools-4.58.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2e6c61ce330142525296170cd65666e46121fc0d44383cbbcfa39cf8f58383df"}, - {file = "fonttools-4.58.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9c75f8faa29579c0fbf29b56ae6a3660c6c025f3b671803cb6a9caa7e4e3a98"}, - {file = "fonttools-4.58.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:88dedcedbd5549e35b2ea3db3de02579c27e62e51af56779c021e7b33caadd0e"}, - {file = "fonttools-4.58.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae80a895adab43586f4da1521d58fd4f4377cef322ee0cc205abcefa3a5effc3"}, - {file = "fonttools-4.58.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0d3acc7f0d151da116e87a182aefb569cf0a3c8e0fd4c9cd0a7c1e7d3e7adb26"}, - {file = "fonttools-4.58.4-cp310-cp310-win32.whl", hash = "sha256:1244f69686008e7e8d2581d9f37eef330a73fee3843f1107993eb82c9d306577"}, - {file = "fonttools-4.58.4-cp310-cp310-win_amd64.whl", hash = "sha256:2a66c0af8a01eb2b78645af60f3b787de5fe5eb1fd8348163715b80bdbfbde1f"}, - {file = "fonttools-4.58.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a3841991c9ee2dc0562eb7f23d333d34ce81e8e27c903846f0487da21e0028eb"}, - {file = "fonttools-4.58.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c98f91b6a9604e7ffb5ece6ea346fa617f967c2c0944228801246ed56084664"}, - {file = "fonttools-4.58.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab9f891eb687ddf6a4e5f82901e00f992e18012ca97ab7acd15f13632acd14c1"}, - {file = "fonttools-4.58.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:891c5771e8f0094b7c0dc90eda8fc75e72930b32581418f2c285a9feedfd9a68"}, - {file = "fonttools-4.58.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:43ba4d9646045c375d22e3473b7d82b18b31ee2ac715cd94220ffab7bc2d5c1d"}, - {file = "fonttools-4.58.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33d19f16e6d2ffd6669bda574a6589941f6c99a8d5cfb9f464038244c71555de"}, - {file = "fonttools-4.58.4-cp311-cp311-win32.whl", hash = "sha256:b59e5109b907da19dc9df1287454821a34a75f2632a491dd406e46ff432c2a24"}, - {file = "fonttools-4.58.4-cp311-cp311-win_amd64.whl", hash = "sha256:3d471a5b567a0d1648f2e148c9a8bcf00d9ac76eb89e976d9976582044cc2509"}, - {file = "fonttools-4.58.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:462211c0f37a278494e74267a994f6be9a2023d0557aaa9ecbcbfce0f403b5a6"}, - {file = "fonttools-4.58.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0c7a12fb6f769165547f00fcaa8d0df9517603ae7e04b625e5acb8639809b82d"}, - {file = "fonttools-4.58.4-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2d42c63020a922154add0a326388a60a55504629edc3274bc273cd3806b4659f"}, - {file = "fonttools-4.58.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f2b4e6fd45edc6805f5f2c355590b092ffc7e10a945bd6a569fc66c1d2ae7aa"}, - {file = "fonttools-4.58.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f155b927f6efb1213a79334e4cb9904d1e18973376ffc17a0d7cd43d31981f1e"}, - {file = "fonttools-4.58.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e38f687d5de97c7fb7da3e58169fb5ba349e464e141f83c3c2e2beb91d317816"}, - {file = "fonttools-4.58.4-cp312-cp312-win32.whl", hash = "sha256:636c073b4da9db053aa683db99580cac0f7c213a953b678f69acbca3443c12cc"}, - {file = "fonttools-4.58.4-cp312-cp312-win_amd64.whl", hash = "sha256:82e8470535743409b30913ba2822e20077acf9ea70acec40b10fcf5671dceb58"}, - {file = "fonttools-4.58.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5f4a64846495c543796fa59b90b7a7a9dff6839bd852741ab35a71994d685c6d"}, - {file = "fonttools-4.58.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e80661793a5d4d7ad132a2aa1eae2e160fbdbb50831a0edf37c7c63b2ed36574"}, - {file = "fonttools-4.58.4-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fe5807fc64e4ba5130f1974c045a6e8d795f3b7fb6debfa511d1773290dbb76b"}, - {file = "fonttools-4.58.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b610b9bef841cb8f4b50472494158b1e347d15cad56eac414c722eda695a6cfd"}, - {file = "fonttools-4.58.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2daa7f0e213c38f05f054eb5e1730bd0424aebddbeac094489ea1585807dd187"}, - {file = "fonttools-4.58.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:66cccb6c0b944496b7f26450e9a66e997739c513ffaac728d24930df2fd9d35b"}, - {file = "fonttools-4.58.4-cp313-cp313-win32.whl", hash = "sha256:94d2aebb5ca59a5107825520fde596e344652c1f18170ef01dacbe48fa60c889"}, - {file = "fonttools-4.58.4-cp313-cp313-win_amd64.whl", hash = "sha256:b554bd6e80bba582fd326ddab296e563c20c64dca816d5e30489760e0c41529f"}, - {file = "fonttools-4.58.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca773fe7812e4e1197ee4e63b9691e89650ab55f679e12ac86052d2fe0d152cd"}, - {file = "fonttools-4.58.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e31289101221910f44245472e02b1a2f7d671c6d06a45c07b354ecb25829ad92"}, - {file = "fonttools-4.58.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90c9e3c01475bb9602cb617f69f02c4ba7ab7784d93f0b0d685e84286f4c1a10"}, - {file = "fonttools-4.58.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e00a826f2bc745a010341ac102082fe5e3fb9f0861b90ed9ff32277598813711"}, - {file = "fonttools-4.58.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc75e72e9d2a4ad0935c59713bd38679d51c6fefab1eadde80e3ed4c2a11ea84"}, - {file = "fonttools-4.58.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f57a795e540059ce3de68508acfaaf177899b39c36ef0a2833b2308db98c71f1"}, - {file = "fonttools-4.58.4-cp39-cp39-win32.whl", hash = "sha256:a7d04f64c88b48ede655abcf76f2b2952f04933567884d99be7c89e0a4495131"}, - {file = "fonttools-4.58.4-cp39-cp39-win_amd64.whl", hash = "sha256:5a8bc5dfd425c89b1c38380bc138787b0a830f761b82b37139aa080915503b69"}, - {file = "fonttools-4.58.4-py3-none-any.whl", hash = "sha256:a10ce13a13f26cbb9f37512a4346bb437ad7e002ff6fa966a7ce7ff5ac3528bd"}, - {file = "fonttools-4.58.4.tar.gz", hash = "sha256:928a8009b9884ed3aae17724b960987575155ca23c6f0b8146e400cc9e0d44ba"}, + {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9a52f254ce051e196b8fe2af4634c2d2f02c981756c6464dc192f1b6050b4e28"}, + {file = "fonttools-4.60.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7420a2696a44650120cdd269a5d2e56a477e2bfa9d95e86229059beb1c19e15"}, + {file = "fonttools-4.60.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee0c0b3b35b34f782afc673d503167157094a16f442ace7c6c5e0ca80b08f50c"}, + {file = "fonttools-4.60.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:282dafa55f9659e8999110bd8ed422ebe1c8aecd0dc396550b038e6c9a08b8ea"}, + {file = "fonttools-4.60.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4ba4bd646e86de16160f0fb72e31c3b9b7d0721c3e5b26b9fa2fc931dfdb2652"}, + {file = "fonttools-4.60.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0b0835ed15dd5b40d726bb61c846a688f5b4ce2208ec68779bc81860adb5851a"}, + {file = "fonttools-4.60.1-cp310-cp310-win32.whl", hash = "sha256:1525796c3ffe27bb6268ed2a1bb0dcf214d561dfaf04728abf01489eb5339dce"}, + {file = "fonttools-4.60.1-cp310-cp310-win_amd64.whl", hash = "sha256:268ecda8ca6cb5c4f044b1fb9b3b376e8cd1b361cef275082429dc4174907038"}, + {file = "fonttools-4.60.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7b4c32e232a71f63a5d00259ca3d88345ce2a43295bb049d21061f338124246f"}, + {file = "fonttools-4.60.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3630e86c484263eaac71d117085d509cbcf7b18f677906824e4bace598fb70d2"}, + {file = "fonttools-4.60.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5c1015318e4fec75dd4943ad5f6a206d9727adf97410d58b7e32ab644a807914"}, + {file = "fonttools-4.60.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e6c58beb17380f7c2ea181ea11e7db8c0ceb474c9dd45f48e71e2cb577d146a1"}, + {file = "fonttools-4.60.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec3681a0cb34c255d76dd9d865a55f260164adb9fa02628415cdc2d43ee2c05d"}, + {file = "fonttools-4.60.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f4b5c37a5f40e4d733d3bbaaef082149bee5a5ea3156a785ff64d949bd1353fa"}, + {file = "fonttools-4.60.1-cp311-cp311-win32.whl", hash = "sha256:398447f3d8c0c786cbf1209711e79080a40761eb44b27cdafffb48f52bcec258"}, + {file = "fonttools-4.60.1-cp311-cp311-win_amd64.whl", hash = "sha256:d066ea419f719ed87bc2c99a4a4bfd77c2e5949cb724588b9dd58f3fd90b92bf"}, + {file = "fonttools-4.60.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7b0c6d57ab00dae9529f3faf187f2254ea0aa1e04215cf2f1a8ec277c96661bc"}, + {file = "fonttools-4.60.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:839565cbf14645952d933853e8ade66a463684ed6ed6c9345d0faf1f0e868877"}, + {file = "fonttools-4.60.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8177ec9676ea6e1793c8a084a90b65a9f778771998eb919d05db6d4b1c0b114c"}, + {file = "fonttools-4.60.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:996a4d1834524adbb423385d5a629b868ef9d774670856c63c9a0408a3063401"}, + {file = "fonttools-4.60.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a46b2f450bc79e06ef3b6394f0c68660529ed51692606ad7f953fc2e448bc903"}, + {file = "fonttools-4.60.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ec722ee589e89a89f5b7574f5c45604030aa6ae24cb2c751e2707193b466fed"}, + {file = "fonttools-4.60.1-cp312-cp312-win32.whl", hash = "sha256:b2cf105cee600d2de04ca3cfa1f74f1127f8455b71dbad02b9da6ec266e116d6"}, + {file = "fonttools-4.60.1-cp312-cp312-win_amd64.whl", hash = "sha256:992775c9fbe2cf794786fa0ffca7f09f564ba3499b8fe9f2f80bd7197db60383"}, + {file = "fonttools-4.60.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6f68576bb4bbf6060c7ab047b1574a1ebe5c50a17de62830079967b211059ebb"}, + {file = "fonttools-4.60.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eedacb5c5d22b7097482fa834bda0dafa3d914a4e829ec83cdea2a01f8c813c4"}, + {file = "fonttools-4.60.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b33a7884fabd72bdf5f910d0cf46be50dce86a0362a65cfc746a4168c67eb96c"}, + {file = "fonttools-4.60.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2409d5fb7b55fd70f715e6d34e7a6e4f7511b8ad29a49d6df225ee76da76dd77"}, + {file = "fonttools-4.60.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8651e0d4b3bdeda6602b85fdc2abbefc1b41e573ecb37b6779c4ca50753a199"}, + {file = "fonttools-4.60.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:145daa14bf24824b677b9357c5e44fd8895c2a8f53596e1b9ea3496081dc692c"}, + {file = "fonttools-4.60.1-cp313-cp313-win32.whl", hash = "sha256:2299df884c11162617a66b7c316957d74a18e3758c0274762d2cc87df7bc0272"}, + {file = "fonttools-4.60.1-cp313-cp313-win_amd64.whl", hash = "sha256:a3db56f153bd4c5c2b619ab02c5db5192e222150ce5a1bc10f16164714bc39ac"}, + {file = "fonttools-4.60.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:a884aef09d45ba1206712c7dbda5829562d3fea7726935d3289d343232ecb0d3"}, + {file = "fonttools-4.60.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8a44788d9d91df72d1a5eac49b31aeb887a5f4aab761b4cffc4196c74907ea85"}, + {file = "fonttools-4.60.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e852d9dda9f93ad3651ae1e3bb770eac544ec93c3807888798eccddf84596537"}, + {file = "fonttools-4.60.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:154cb6ee417e417bf5f7c42fe25858c9140c26f647c7347c06f0cc2d47eff003"}, + {file = "fonttools-4.60.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5664fd1a9ea7f244487ac8f10340c4e37664675e8667d6fee420766e0fb3cf08"}, + {file = "fonttools-4.60.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:583b7f8e3c49486e4d489ad1deacfb8d5be54a8ef34d6df824f6a171f8511d99"}, + {file = "fonttools-4.60.1-cp314-cp314-win32.whl", hash = "sha256:66929e2ea2810c6533a5184f938502cfdaea4bc3efb7130d8cc02e1c1b4108d6"}, + {file = "fonttools-4.60.1-cp314-cp314-win_amd64.whl", hash = "sha256:f3d5be054c461d6a2268831f04091dc82753176f6ea06dc6047a5e168265a987"}, + {file = "fonttools-4.60.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b6379e7546ba4ae4b18f8ae2b9bc5960936007a1c0e30b342f662577e8bc3299"}, + {file = "fonttools-4.60.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9d0ced62b59e0430b3690dbc5373df1c2aa7585e9a8ce38eff87f0fd993c5b01"}, + {file = "fonttools-4.60.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:875cb7764708b3132637f6c5fb385b16eeba0f7ac9fa45a69d35e09b47045801"}, + {file = "fonttools-4.60.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a184b2ea57b13680ab6d5fbde99ccef152c95c06746cb7718c583abd8f945ccc"}, + {file = "fonttools-4.60.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:026290e4ec76583881763fac284aca67365e0be9f13a7fb137257096114cb3bc"}, + {file = "fonttools-4.60.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f0e8817c7d1a0c2eedebf57ef9a9896f3ea23324769a9a2061a80fe8852705ed"}, + {file = "fonttools-4.60.1-cp314-cp314t-win32.whl", hash = "sha256:1410155d0e764a4615774e5c2c6fc516259fe3eca5882f034eb9bfdbee056259"}, + {file = "fonttools-4.60.1-cp314-cp314t-win_amd64.whl", hash = "sha256:022beaea4b73a70295b688f817ddc24ed3e3418b5036ffcd5658141184ef0d0c"}, + {file = "fonttools-4.60.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:122e1a8ada290423c493491d002f622b1992b1ab0b488c68e31c413390dc7eb2"}, + {file = "fonttools-4.60.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a140761c4ff63d0cb9256ac752f230460ee225ccef4ad8f68affc723c88e2036"}, + {file = "fonttools-4.60.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0eae96373e4b7c9e45d099d7a523444e3554360927225c1cdae221a58a45b856"}, + {file = "fonttools-4.60.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:596ecaca36367027d525b3b426d8a8208169d09edcf8c7506aceb3a38bfb55c7"}, + {file = "fonttools-4.60.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2ee06fc57512144d8b0445194c2da9f190f61ad51e230f14836286470c99f854"}, + {file = "fonttools-4.60.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b42d86938e8dda1cd9a1a87a6d82f1818eaf933348429653559a458d027446da"}, + {file = "fonttools-4.60.1-cp39-cp39-win32.whl", hash = "sha256:8b4eb332f9501cb1cd3d4d099374a1e1306783ff95489a1026bde9eb02ccc34a"}, + {file = "fonttools-4.60.1-cp39-cp39-win_amd64.whl", hash = "sha256:7473a8ed9ed09aeaa191301244a5a9dbe46fe0bf54f9d6cd21d83044c3321217"}, + {file = "fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb"}, + {file = "fonttools-4.60.1.tar.gz", hash = "sha256:ef00af0439ebfee806b25f24c8f92109157ff3fac5731dc7867957812e87b8d9"}, ] [package.extras] -all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] +all = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\"", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0) ; python_version <= \"3.12\"", "xattr ; sys_platform == \"darwin\"", "zopfli (>=0.1.4)"] graphite = ["lz4 (>=1.7.4.2)"] interpolatable = ["munkres ; platform_python_implementation == \"PyPy\"", "pycairo", "scipy ; platform_python_implementation != \"PyPy\""] lxml = ["lxml (>=4.0)"] @@ -469,7 +558,6 @@ plot = ["matplotlib"] repacker = ["uharfbuzz (>=0.23.0)"] symfont = ["sympy"] type1 = ["xattr ; sys_platform == \"darwin\""] -ufo = ["fs (>=2.2.0,<3)"] unicode = ["unicodedata2 (>=15.1.0) ; python_version <= \"3.12\""] woff = ["brotli (>=1.0.1) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\"", "zopfli (>=0.1.4)"] @@ -575,26 +663,26 @@ files = [ [[package]] name = "joblib" -version = "1.5.1" +version = "1.5.2" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a"}, - {file = "joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444"}, + {file = "joblib-1.5.2-py3-none-any.whl", hash = "sha256:4e1f0bdbb987e6d843c70cf43714cb276623def372df3c22fe5266b2670bc241"}, + {file = "joblib-1.5.2.tar.gz", hash = "sha256:3faa5c39054b2f03ca547da9b2f52fde67c06240c31853f306aea97f13647b55"}, ] [[package]] name = "jsonschema" -version = "4.24.0" +version = "4.25.1" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "jsonschema-4.24.0-py3-none-any.whl", hash = "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d"}, - {file = "jsonschema-4.24.0.tar.gz", hash = "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196"}, + {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, + {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, ] [package.dependencies] @@ -605,18 +693,18 @@ rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] [[package]] name = "jsonschema-specifications" -version = "2025.4.1" +version = "2025.9.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"}, - {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"}, + {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, + {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, ] [package.dependencies] @@ -650,6 +738,7 @@ description = "A fast implementation of the Cassowary constraint solver" optional = false python-versions = ">=3.8" groups = ["main"] +markers = "python_version < \"3.11\"" files = [ {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, @@ -767,6 +856,118 @@ files = [ {file = "kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60"}, ] +[[package]] +name = "kiwisolver" +version = "1.4.9" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b"}, + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f"}, + {file = "kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b"}, + {file = "kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586"}, + {file = "kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634"}, + {file = "kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611"}, + {file = "kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089"}, + {file = "kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc1ae486f9abcef254b5618dfb4113dd49f94c68e3e027d03cf0143f3f772b61"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8a1f570ce4d62d718dce3f179ee78dac3b545ac16c0c04bb363b7607a949c0d1"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb27e7b78d716c591e88e0a09a2139c6577865d7f2e152488c2cc6257f460872"}, + {file = "kiwisolver-1.4.9-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:15163165efc2f627eb9687ea5f3a28137217d217ac4024893d753f46bce9de26"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bdee92c56a71d2b24c33a7d4c2856bd6419d017e08caa7802d2963870e315028"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:412f287c55a6f54b0650bd9b6dce5aceddb95864a1a90c87af16979d37c89771"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2c93f00dcba2eea70af2be5f11a830a742fe6b579a1d4e00f47760ef13be247a"}, + {file = "kiwisolver-1.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f117e1a089d9411663a3207ba874f31be9ac8eaa5b533787024dc07aeb74f464"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_amd64.whl", hash = "sha256:be6a04e6c79819c9a8c2373317d19a96048e5a3f90bec587787e86a1153883c2"}, + {file = "kiwisolver-1.4.9-cp311-cp311-win_arm64.whl", hash = "sha256:0ae37737256ba2de764ddc12aed4956460277f00c4996d51a197e72f62f5eec7"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ac5a486ac389dddcc5bef4f365b6ae3ffff2c433324fb38dd35e3fab7c957999"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f2ba92255faa7309d06fe44c3a4a97efe1c8d640c2a79a5ef728b685762a6fd2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a2899935e724dd1074cb568ce7ac0dce28b2cd6ab539c8e001a8578eb106d14"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f6008a4919fdbc0b0097089f67a1eb55d950ed7e90ce2cc3e640abadd2757a04"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67bb8b474b4181770f926f7b7d2f8c0248cbcb78b660fdd41a47054b28d2a752"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2327a4a30d3ee07d2fbe2e7933e8a37c591663b96ce42a00bc67461a87d7df77"}, + {file = "kiwisolver-1.4.9-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7a08b491ec91b1d5053ac177afe5290adacf1f0f6307d771ccac5de30592d198"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8fc5c867c22b828001b6a38d2eaeb88160bf5783c6cb4a5e440efc981ce286d"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3b3115b2581ea35bb6d1f24a4c90af37e5d9b49dcff267eeed14c3893c5b86ab"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:858e4c22fb075920b96a291928cb7dea5644e94c0ee4fcd5af7e865655e4ccf2"}, + {file = "kiwisolver-1.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ed0fecd28cc62c54b262e3736f8bb2512d8dcfdc2bcf08be5f47f96bf405b145"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_amd64.whl", hash = "sha256:f68208a520c3d86ea51acf688a3e3002615a7f0238002cccc17affecc86a8a54"}, + {file = "kiwisolver-1.4.9-cp312-cp312-win_arm64.whl", hash = "sha256:2c1a4f57df73965f3f14df20b80ee29e6a7930a57d2d9e8491a25f676e197c60"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2"}, + {file = "kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525"}, + {file = "kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3"}, + {file = "kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c"}, + {file = "kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d"}, + {file = "kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07"}, + {file = "kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552"}, + {file = "kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df"}, + {file = "kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5"}, + {file = "kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce"}, + {file = "kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7"}, + {file = "kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891"}, + {file = "kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9"}, + {file = "kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:464415881e4801295659462c49461a24fb107c140de781d55518c4b80cb6790f"}, + {file = "kiwisolver-1.4.9-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:fb940820c63a9590d31d88b815e7a3aa5915cad3ce735ab45f0c730b39547de1"}, + {file = "kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d"}, +] + [[package]] name = "lxml" version = "5.4.0" @@ -918,14 +1119,14 @@ source = ["Cython (>=3.0.11,<3.1.0)"] [[package]] name = "markdown" -version = "3.8.1" +version = "3.9" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "markdown-3.8.1-py3-none-any.whl", hash = "sha256:46cc0c0f1e5211ab2e9d453582f0b28a1bfaf058a9f7d5c50386b99b588d8811"}, - {file = "markdown-3.8.1.tar.gz", hash = "sha256:a2e2f01cead4828ee74ecca9623045f62216aef2212a7685d6eb9163f590b8c1"}, + {file = "markdown-3.9-py3-none-any.whl", hash = "sha256:9f4d91ed810864ea88a6f32c07ba8bee1346c0cc1f6b1f9f6c822f2a9667d280"}, + {file = "markdown-3.9.tar.gz", hash = "sha256:d2900fe1782bd33bdbbd56859defef70c2e78fc46668f8eb9df3128138f2cb6a"}, ] [package.dependencies] @@ -935,6 +1136,31 @@ importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "matplotlib" version = "3.9.4" @@ -1001,16 +1227,28 @@ python-dateutil = ">=2.7" [package.extras] dev = ["meson-python (>=0.13.1,<0.17.0)", "numpy (>=1.25)", "pybind11 (>=2.6,!=2.13.3)", "setuptools (>=64)", "setuptools_scm (>=7)"] +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + [[package]] name = "more-itertools" -version = "10.7.0" +version = "10.8.0" description = "More routines for operating on iterables, beyond itertools" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e"}, - {file = "more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3"}, + {file = "more_itertools-10.8.0-py3-none-any.whl", hash = "sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b"}, + {file = "more_itertools-10.8.0.tar.gz", hash = "sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd"}, ] [[package]] @@ -1037,14 +1275,14 @@ test = ["pep440", "pre-commit", "pytest", "testpath"] [[package]] name = "nltk" -version = "3.9.1" +version = "3.9.2" description = "Natural Language Toolkit" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, - {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, + {file = "nltk-3.9.2-py3-none-any.whl", hash = "sha256:1e209d2b3009110635ed9709a67a1a3e33a10f799490fa71cf4bec218c11c88a"}, + {file = "nltk-3.9.2.tar.gz", hash = "sha256:0f409e9b069ca4177c1903c3e843eef90c7e92992fa4931ae607da6de49e1419"}, ] [package.dependencies] @@ -1121,54 +1359,67 @@ files = [ [[package]] name = "pandas" -version = "2.3.0" +version = "2.3.3" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pandas-2.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:625466edd01d43b75b1883a64d859168e4556261a5035b32f9d743b67ef44634"}, - {file = "pandas-2.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6872d695c896f00df46b71648eea332279ef4077a409e2fe94220208b6bb675"}, - {file = "pandas-2.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4dd97c19bd06bc557ad787a15b6489d2614ddaab5d104a0310eb314c724b2d2"}, - {file = "pandas-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:034abd6f3db8b9880aaee98f4f5d4dbec7c4829938463ec046517220b2f8574e"}, - {file = "pandas-2.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:23c2b2dc5213810208ca0b80b8666670eb4660bbfd9d45f58592cc4ddcfd62e1"}, - {file = "pandas-2.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:39ff73ec07be5e90330cc6ff5705c651ace83374189dcdcb46e6ff54b4a72cd6"}, - {file = "pandas-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:40cecc4ea5abd2921682b57532baea5588cc5f80f0231c624056b146887274d2"}, - {file = "pandas-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8adff9f138fc614347ff33812046787f7d43b3cef7c0f0171b3340cae333f6ca"}, - {file = "pandas-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e5f08eb9a445d07720776df6e641975665c9ea12c9d8a331e0f6890f2dcd76ef"}, - {file = "pandas-2.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa35c266c8cd1a67d75971a1912b185b492d257092bdd2709bbdebe574ed228d"}, - {file = "pandas-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14a0cc77b0f089d2d2ffe3007db58f170dae9b9f54e569b299db871a3ab5bf46"}, - {file = "pandas-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c06f6f144ad0a1bf84699aeea7eff6068ca5c63ceb404798198af7eb86082e33"}, - {file = "pandas-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed16339bc354a73e0a609df36d256672c7d296f3f767ac07257801aa064ff73c"}, - {file = "pandas-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:fa07e138b3f6c04addfeaf56cc7fdb96c3b68a3fe5e5401251f231fce40a0d7a"}, - {file = "pandas-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf"}, - {file = "pandas-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027"}, - {file = "pandas-2.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09"}, - {file = "pandas-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d"}, - {file = "pandas-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20"}, - {file = "pandas-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b"}, - {file = "pandas-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be"}, - {file = "pandas-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983"}, - {file = "pandas-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd"}, - {file = "pandas-2.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f"}, - {file = "pandas-2.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3"}, - {file = "pandas-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8"}, - {file = "pandas-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9"}, - {file = "pandas-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390"}, - {file = "pandas-2.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575"}, - {file = "pandas-2.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042"}, - {file = "pandas-2.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c"}, - {file = "pandas-2.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67"}, - {file = "pandas-2.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f"}, - {file = "pandas-2.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249"}, - {file = "pandas-2.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9efc0acbbffb5236fbdf0409c04edce96bec4bdaa649d49985427bd1ec73e085"}, - {file = "pandas-2.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:75651c14fde635e680496148a8526b328e09fe0572d9ae9b638648c46a544ba3"}, - {file = "pandas-2.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf5be867a0541a9fb47a4be0c5790a4bccd5b77b92f0a59eeec9375fafc2aa14"}, - {file = "pandas-2.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84141f722d45d0c2a89544dd29d35b3abfc13d2250ed7e68394eda7564bd6324"}, - {file = "pandas-2.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f95a2aef32614ed86216d3c450ab12a4e82084e8102e355707a1d96e33d51c34"}, - {file = "pandas-2.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e0f51973ba93a9f97185049326d75b942b9aeb472bec616a129806facb129ebb"}, - {file = "pandas-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b198687ca9c8529662213538a9bb1e60fa0bf0f6af89292eb68fea28743fcd5a"}, - {file = "pandas-2.3.0.tar.gz", hash = "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, + {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, + {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, + {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, + {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, + {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, + {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, + {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, ] [package.dependencies] @@ -1208,114 +1459,139 @@ xml = ["lxml (>=4.9.2)"] [[package]] name = "pillow" -version = "11.2.1" +version = "11.3.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pillow-11.2.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:d57a75d53922fc20c165016a20d9c44f73305e67c351bbc60d1adaf662e74047"}, - {file = "pillow-11.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:127bf6ac4a5b58b3d32fc8289656f77f80567d65660bc46f72c0d77e6600cc95"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4ba4be812c7a40280629e55ae0b14a0aafa150dd6451297562e1764808bbe61"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8bd62331e5032bc396a93609982a9ab6b411c05078a52f5fe3cc59234a3abd1"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:562d11134c97a62fe3af29581f083033179f7ff435f78392565a1ad2d1c2c45c"}, - {file = "pillow-11.2.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c97209e85b5be259994eb5b69ff50c5d20cca0f458ef9abd835e262d9d88b39d"}, - {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0c3e6d0f59171dfa2e25d7116217543310908dfa2770aa64b8f87605f8cacc97"}, - {file = "pillow-11.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cc1c3bc53befb6096b84165956e886b1729634a799e9d6329a0c512ab651e579"}, - {file = "pillow-11.2.1-cp310-cp310-win32.whl", hash = "sha256:312c77b7f07ab2139924d2639860e084ec2a13e72af54d4f08ac843a5fc9c79d"}, - {file = "pillow-11.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:9bc7ae48b8057a611e5fe9f853baa88093b9a76303937449397899385da06fad"}, - {file = "pillow-11.2.1-cp310-cp310-win_arm64.whl", hash = "sha256:2728567e249cdd939f6cc3d1f049595c66e4187f3c34078cbc0a7d21c47482d2"}, - {file = "pillow-11.2.1-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35ca289f712ccfc699508c4658a1d14652e8033e9b69839edf83cbdd0ba39e70"}, - {file = "pillow-11.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0409af9f829f87a2dfb7e259f78f317a5351f2045158be321fd135973fff7bf"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4e5c5edee874dce4f653dbe59db7c73a600119fbea8d31f53423586ee2aafd7"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93a07e76d13bff9444f1a029e0af2964e654bfc2e2c2d46bfd080df5ad5f3d8"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:e6def7eed9e7fa90fde255afaf08060dc4b343bbe524a8f69bdd2a2f0018f600"}, - {file = "pillow-11.2.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8f4f3724c068be008c08257207210c138d5f3731af6c155a81c2b09a9eb3a788"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a0a6709b47019dff32e678bc12c63008311b82b9327613f534e496dacaefb71e"}, - {file = "pillow-11.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f6b0c664ccb879109ee3ca702a9272d877f4fcd21e5eb63c26422fd6e415365e"}, - {file = "pillow-11.2.1-cp311-cp311-win32.whl", hash = "sha256:cc5d875d56e49f112b6def6813c4e3d3036d269c008bf8aef72cd08d20ca6df6"}, - {file = "pillow-11.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:0f5c7eda47bf8e3c8a283762cab94e496ba977a420868cb819159980b6709193"}, - {file = "pillow-11.2.1-cp311-cp311-win_arm64.whl", hash = "sha256:4d375eb838755f2528ac8cbc926c3e31cc49ca4ad0cf79cff48b20e30634a4a7"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:78afba22027b4accef10dbd5eed84425930ba41b3ea0a86fa8d20baaf19d807f"}, - {file = "pillow-11.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78092232a4ab376a35d68c4e6d5e00dfd73454bd12b230420025fbe178ee3b0b"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a5f306095c6780c52e6bbb6109624b95c5b18e40aab1c3041da3e9e0cd3e2d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c7b29dbd4281923a2bfe562acb734cee96bbb129e96e6972d315ed9f232bef4"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:3e645b020f3209a0181a418bffe7b4a93171eef6c4ef6cc20980b30bebf17b7d"}, - {file = "pillow-11.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:b2dbea1012ccb784a65349f57bbc93730b96e85b42e9bf7b01ef40443db720b4"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:da3104c57bbd72948d75f6a9389e6727d2ab6333c3617f0a89d72d4940aa0443"}, - {file = "pillow-11.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:598174aef4589af795f66f9caab87ba4ff860ce08cd5bb447c6fc553ffee603c"}, - {file = "pillow-11.2.1-cp312-cp312-win32.whl", hash = "sha256:1d535df14716e7f8776b9e7fee118576d65572b4aad3ed639be9e4fa88a1cad3"}, - {file = "pillow-11.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:14e33b28bf17c7a38eede290f77db7c664e4eb01f7869e37fa98a5aa95978941"}, - {file = "pillow-11.2.1-cp312-cp312-win_arm64.whl", hash = "sha256:21e1470ac9e5739ff880c211fc3af01e3ae505859392bf65458c224d0bf283eb"}, - {file = "pillow-11.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fdec757fea0b793056419bca3e9932eb2b0ceec90ef4813ea4c1e072c389eb28"}, - {file = "pillow-11.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0e130705d568e2f43a17bcbe74d90958e8a16263868a12c3e0d9c8162690830"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bdb5e09068332578214cadd9c05e3d64d99e0e87591be22a324bdbc18925be0"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d189ba1bebfbc0c0e529159631ec72bb9e9bc041f01ec6d3233d6d82eb823bc1"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:191955c55d8a712fab8934a42bfefbf99dd0b5875078240943f913bb66d46d9f"}, - {file = "pillow-11.2.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:ad275964d52e2243430472fc5d2c2334b4fc3ff9c16cb0a19254e25efa03a155"}, - {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:750f96efe0597382660d8b53e90dd1dd44568a8edb51cb7f9d5d918b80d4de14"}, - {file = "pillow-11.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fe15238d3798788d00716637b3d4e7bb6bde18b26e5d08335a96e88564a36b6b"}, - {file = "pillow-11.2.1-cp313-cp313-win32.whl", hash = "sha256:3fe735ced9a607fee4f481423a9c36701a39719252a9bb251679635f99d0f7d2"}, - {file = "pillow-11.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:74ee3d7ecb3f3c05459ba95eed5efa28d6092d751ce9bf20e3e253a4e497e691"}, - {file = "pillow-11.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:5119225c622403afb4b44bad4c1ca6c1f98eed79db8d3bc6e4e160fc6339d66c"}, - {file = "pillow-11.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8ce2e8411c7aaef53e6bb29fe98f28cd4fbd9a1d9be2eeea434331aac0536b22"}, - {file = "pillow-11.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:9ee66787e095127116d91dea2143db65c7bb1e232f617aa5957c0d9d2a3f23a7"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9622e3b6c1d8b551b6e6f21873bdcc55762b4b2126633014cea1803368a9aa16"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63b5dff3a68f371ea06025a1a6966c9a1e1ee452fc8020c2cd0ea41b83e9037b"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:31df6e2d3d8fc99f993fd253e97fae451a8db2e7207acf97859732273e108406"}, - {file = "pillow-11.2.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:062b7a42d672c45a70fa1f8b43d1d38ff76b63421cbbe7f88146b39e8a558d91"}, - {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4eb92eca2711ef8be42fd3f67533765d9fd043b8c80db204f16c8ea62ee1a751"}, - {file = "pillow-11.2.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f91ebf30830a48c825590aede79376cb40f110b387c17ee9bd59932c961044f9"}, - {file = "pillow-11.2.1-cp313-cp313t-win32.whl", hash = "sha256:e0b55f27f584ed623221cfe995c912c61606be8513bfa0e07d2c674b4516d9dd"}, - {file = "pillow-11.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:36d6b82164c39ce5482f649b437382c0fb2395eabc1e2b1702a6deb8ad647d6e"}, - {file = "pillow-11.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:225c832a13326e34f212d2072982bb1adb210e0cc0b153e688743018c94a2681"}, - {file = "pillow-11.2.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:7491cf8a79b8eb867d419648fff2f83cb0b3891c8b36da92cc7f1931d46108c8"}, - {file = "pillow-11.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b02d8f9cb83c52578a0b4beadba92e37d83a4ef11570a8688bbf43f4ca50909"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:014ca0050c85003620526b0ac1ac53f56fc93af128f7546623cc8e31875ab928"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3692b68c87096ac6308296d96354eddd25f98740c9d2ab54e1549d6c8aea9d79"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:f781dcb0bc9929adc77bad571b8621ecb1e4cdef86e940fe2e5b5ee24fd33b35"}, - {file = "pillow-11.2.1-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:2b490402c96f907a166615e9a5afacf2519e28295f157ec3a2bb9bd57de638cb"}, - {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd6b20b93b3ccc9c1b597999209e4bc5cf2853f9ee66e3fc9a400a78733ffc9a"}, - {file = "pillow-11.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4b835d89c08a6c2ee7781b8dd0a30209a8012b5f09c0a665b65b0eb3560b6f36"}, - {file = "pillow-11.2.1-cp39-cp39-win32.whl", hash = "sha256:b10428b3416d4f9c61f94b494681280be7686bda15898a3a9e08eb66a6d92d67"}, - {file = "pillow-11.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:6ebce70c3f486acf7591a3d73431fa504a4e18a9b97ff27f5f47b7368e4b9dd1"}, - {file = "pillow-11.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:c27476257b2fdcd7872d54cfd119b3a9ce4610fb85c8e32b70b42e3680a29a1e"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9b7b0d4fd2635f54ad82785d56bc0d94f147096493a79985d0ab57aedd563156"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:aa442755e31c64037aa7c1cb186e0b369f8416c567381852c63444dd666fb772"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0d3348c95b766f54b76116d53d4cb171b52992a1027e7ca50c81b43b9d9e363"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85d27ea4c889342f7e35f6d56e7e1cb345632ad592e8c51b693d7b7556043ce0"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bf2c33d6791c598142f00c9c4c7d47f6476731c31081331664eb26d6ab583e01"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e616e7154c37669fc1dfc14584f11e284e05d1c650e1c0f972f281c4ccc53193"}, - {file = "pillow-11.2.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:39ad2e0f424394e3aebc40168845fee52df1394a4673a6ee512d840d14ab3013"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:80f1df8dbe9572b4b7abdfa17eb5d78dd620b1d55d9e25f834efdbee872d3aed"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:ea926cfbc3957090becbcbbb65ad177161a2ff2ad578b5a6ec9bb1e1cd78753c"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:738db0e0941ca0376804d4de6a782c005245264edaa253ffce24e5a15cbdc7bd"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db98ab6565c69082ec9b0d4e40dd9f6181dab0dd236d26f7a50b8b9bfbd5076"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:036e53f4170e270ddb8797d4c590e6dd14d28e15c7da375c18978045f7e6c37b"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:14f73f7c291279bd65fda51ee87affd7c1e097709f7fdd0188957a16c264601f"}, - {file = "pillow-11.2.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:208653868d5c9ecc2b327f9b9ef34e0e42a4cdd172c2988fd81d62d2bc9bc044"}, - {file = "pillow-11.2.1.tar.gz", hash = "sha256:a64dd61998416367b7ef979b73d3a85853ba9bec4c2925f74e588879a58716b6"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1b9c17fd4ace828b3003dfd1e30bff24863e0eb59b535e8f80194d9cc7ecf860"}, + {file = "pillow-11.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:65dc69160114cdd0ca0f35cb434633c75e8e7fad4cf855177a05bf38678f73ad"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7107195ddc914f656c7fc8e4a5e1c25f32e9236ea3ea860f257b0436011fddd0"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc3e831b563b3114baac7ec2ee86819eb03caa1a2cef0b481a5675b59c4fe23b"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f182ebd2303acf8c380a54f615ec883322593320a9b00438eb842c1f37ae50"}, + {file = "pillow-11.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4445fa62e15936a028672fd48c4c11a66d641d2c05726c7ec1f8ba6a572036ae"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71f511f6b3b91dd543282477be45a033e4845a40278fa8dcdbfdb07109bf18f9"}, + {file = "pillow-11.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:040a5b691b0713e1f6cbe222e0f4f74cd233421e105850ae3b3c0ceda520f42e"}, + {file = "pillow-11.3.0-cp310-cp310-win32.whl", hash = "sha256:89bd777bc6624fe4115e9fac3352c79ed60f3bb18651420635f26e643e3dd1f6"}, + {file = "pillow-11.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:19d2ff547c75b8e3ff46f4d9ef969a06c30ab2d4263a9e287733aa8b2429ce8f"}, + {file = "pillow-11.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:819931d25e57b513242859ce1876c58c59dc31587847bf74cfe06b2e0cb22d2f"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1cd110edf822773368b396281a2293aeb91c90a2db00d78ea43e7e861631b722"}, + {file = "pillow-11.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c412fddd1b77a75aa904615ebaa6001f169b26fd467b4be93aded278266b288"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1aa4de119a0ecac0a34a9c8bde33f34022e2e8f99104e47a3ca392fd60e37d"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:91da1d88226663594e3f6b4b8c3c8d85bd504117d043740a8e0ec449087cc494"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643f189248837533073c405ec2f0bb250ba54598cf80e8c1e043381a60632f58"}, + {file = "pillow-11.3.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:106064daa23a745510dabce1d84f29137a37224831d88eb4ce94bb187b1d7e5f"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cd8ff254faf15591e724dc7c4ddb6bf4793efcbe13802a4ae3e863cd300b493e"}, + {file = "pillow-11.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:932c754c2d51ad2b2271fd01c3d121daaa35e27efae2a616f77bf164bc0b3e94"}, + {file = "pillow-11.3.0-cp311-cp311-win32.whl", hash = "sha256:b4b8f3efc8d530a1544e5962bd6b403d5f7fe8b9e08227c6b255f98ad82b4ba0"}, + {file = "pillow-11.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:1a992e86b0dd7aeb1f053cd506508c0999d710a8f07b4c791c63843fc6a807ac"}, + {file = "pillow-11.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:30807c931ff7c095620fe04448e2c2fc673fcbb1ffe2a7da3fb39613489b1ddd"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdae223722da47b024b867c1ea0be64e0df702c5e0a60e27daad39bf960dd1e4"}, + {file = "pillow-11.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:921bd305b10e82b4d1f5e802b6850677f965d8394203d182f078873851dada69"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:eb76541cba2f958032d79d143b98a3a6b3ea87f0959bbe256c0b5e416599fd5d"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67172f2944ebba3d4a7b54f2e95c786a3a50c21b88456329314caaa28cda70f6"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f07ed9f56a3b9b5f49d3661dc9607484e85c67e27f3e8be2c7d28ca032fec7"}, + {file = "pillow-11.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:676b2815362456b5b3216b4fd5bd89d362100dc6f4945154ff172e206a22c024"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3e184b2f26ff146363dd07bde8b711833d7b0202e27d13540bfe2e35a323a809"}, + {file = "pillow-11.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6be31e3fc9a621e071bc17bb7de63b85cbe0bfae91bb0363c893cbe67247780d"}, + {file = "pillow-11.3.0-cp312-cp312-win32.whl", hash = "sha256:7b161756381f0918e05e7cb8a371fff367e807770f8fe92ecb20d905d0e1c149"}, + {file = "pillow-11.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a6444696fce635783440b7f7a9fc24b3ad10a9ea3f0ab66c5905be1c19ccf17d"}, + {file = "pillow-11.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:2aceea54f957dd4448264f9bf40875da0415c83eb85f55069d89c0ed436e3542"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:1c627742b539bba4309df89171356fcb3cc5a9178355b2727d1b74a6cf155fbd"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:30b7c02f3899d10f13d7a48163c8969e4e653f8b43416d23d13d1bbfdc93b9f8"}, + {file = "pillow-11.3.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7859a4cc7c9295f5838015d8cc0a9c215b77e43d07a25e460f35cf516df8626f"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec1ee50470b0d050984394423d96325b744d55c701a439d2bd66089bff963d3c"}, + {file = "pillow-11.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7db51d222548ccfd274e4572fdbf3e810a5e66b00608862f947b163e613b67dd"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2d6fcc902a24ac74495df63faad1884282239265c6839a0a6416d33faedfae7e"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0f5d8f4a08090c6d6d578351a2b91acf519a54986c055af27e7a93feae6d3f1"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c37d8ba9411d6003bba9e518db0db0c58a680ab9fe5179f040b0463644bc9805"}, + {file = "pillow-11.3.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13f87d581e71d9189ab21fe0efb5a23e9f28552d5be6979e84001d3b8505abe8"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:023f6d2d11784a465f09fd09a34b150ea4672e85fb3d05931d89f373ab14abb2"}, + {file = "pillow-11.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:45dfc51ac5975b938e9809451c51734124e73b04d0f0ac621649821a63852e7b"}, + {file = "pillow-11.3.0-cp313-cp313-win32.whl", hash = "sha256:a4d336baed65d50d37b88ca5b60c0fa9d81e3a87d4a7930d3880d1624d5b31f3"}, + {file = "pillow-11.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0bce5c4fd0921f99d2e858dc4d4d64193407e1b99478bc5cacecba2311abde51"}, + {file = "pillow-11.3.0-cp313-cp313-win_arm64.whl", hash = "sha256:1904e1264881f682f02b7f8167935cce37bc97db457f8e7849dc3a6a52b99580"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4c834a3921375c48ee6b9624061076bc0a32a60b5532b322cc0ea64e639dd50e"}, + {file = "pillow-11.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e05688ccef30ea69b9317a9ead994b93975104a677a36a8ed8106be9260aa6d"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1019b04af07fc0163e2810167918cb5add8d74674b6267616021ab558dc98ced"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f944255db153ebb2b19c51fe85dd99ef0ce494123f21b9db4877ffdfc5590c7c"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1f85acb69adf2aaee8b7da124efebbdb959a104db34d3a2cb0f3793dbae422a8"}, + {file = "pillow-11.3.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:05f6ecbeff5005399bb48d198f098a9b4b6bdf27b8487c7f38ca16eeb070cd59"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a7bc6e6fd0395bc052f16b1a8670859964dbd7003bd0af2ff08342eb6e442cfe"}, + {file = "pillow-11.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:83e1b0161c9d148125083a35c1c5a89db5b7054834fd4387499e06552035236c"}, + {file = "pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788"}, + {file = "pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31"}, + {file = "pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12"}, + {file = "pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027"}, + {file = "pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874"}, + {file = "pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a"}, + {file = "pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214"}, + {file = "pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635"}, + {file = "pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae"}, + {file = "pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b"}, + {file = "pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50"}, + {file = "pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b"}, + {file = "pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12"}, + {file = "pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db"}, + {file = "pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:48d254f8a4c776de343051023eb61ffe818299eeac478da55227d96e241de53f"}, + {file = "pillow-11.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7aee118e30a4cf54fdd873bd3a29de51e29105ab11f9aad8c32123f58c8f8081"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:23cff760a9049c502721bdb743a7cb3e03365fafcdfc2ef9784610714166e5a4"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6359a3bc43f57d5b375d1ad54a0074318a0844d11b76abccf478c37c986d3cfc"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:092c80c76635f5ecb10f3f83d76716165c96f5229addbd1ec2bdbbda7d496e06"}, + {file = "pillow-11.3.0-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cadc9e0ea0a2431124cde7e1697106471fc4c1da01530e679b2391c37d3fbb3a"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6a418691000f2a418c9135a7cf0d797c1bb7d9a485e61fe8e7722845b95ef978"}, + {file = "pillow-11.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:97afb3a00b65cc0804d1c7abddbf090a81eaac02768af58cbdcaaa0a931e0b6d"}, + {file = "pillow-11.3.0-cp39-cp39-win32.whl", hash = "sha256:ea944117a7974ae78059fcc1800e5d3295172bb97035c0c1d9345fca1419da71"}, + {file = "pillow-11.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:e5c5858ad8ec655450a7c7df532e9842cf8df7cc349df7225c60d5d348c8aada"}, + {file = "pillow-11.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:6abdbfd3aea42be05702a8dd98832329c167ee84400a1d1f61ab11437f1717eb"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3cee80663f29e3843b68199b9d6f4f54bd1d4a6b59bdd91bceefc51238bcb967"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b5f56c3f344f2ccaf0dd875d3e180f631dc60a51b314295a3e681fe8cf851fbe"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e67d793d180c9df62f1f40aee3accca4829d3794c95098887edc18af4b8b780c"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d000f46e2917c705e9fb93a3606ee4a819d1e3aa7a9b442f6444f07e77cf5e25"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527b37216b6ac3a12d7838dc3bd75208ec57c1c6d11ef01902266a5a0c14fc27"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5463ac478b623b9dd3937afd7fb7ab3d79dd290a28e2b6df292dc75063eb8a"}, + {file = "pillow-11.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8dc70ca24c110503e16918a658b869019126ecfe03109b754c402daff12b3d9f"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:465b9e8844e3c3519a983d58b80be3f668e2a7a5db97f2784e7079fbc9f9822c"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5418b53c0d59b3824d05e029669efa023bbef0f3e92e75ec8428f3799487f361"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:504b6f59505f08ae014f724b6207ff6222662aab5cc9542577fb084ed0676ac7"}, + {file = "pillow-11.3.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c84d689db21a1c397d001aa08241044aa2069e7587b398c8cc63020390b1c1b8"}, + {file = "pillow-11.3.0.tar.gz", hash = "sha256:3828ee7586cd0b2091b6209e5ad53e20d0649bbe87164a459d0676e035e8f523"}, ] [package.extras] -docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] test-arrow = ["pyarrow"] -tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "trove-classifiers (>=2024.10.12)"] typing = ["typing-extensions ; python_version < \"3.10\""] xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.3.8" +version = "4.4.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, + {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, + {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, ] [package.extras] @@ -1380,14 +1656,14 @@ testing = ["pytest", "setuptools", "twine", "wheel"] [[package]] name = "pyparsing" -version = "3.2.3" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" +version = "3.2.5" +description = "pyparsing - Classes and methods to define and execute parsing grammars" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, - {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, + {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"}, + {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"}, ] [package.extras] @@ -1445,92 +1721,116 @@ files = [ [[package]] name = "pywin32" -version = "310" +version = "311" description = "Python for Window Extensions" optional = false python-versions = "*" groups = ["main"] markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"" files = [ - {file = "pywin32-310-cp310-cp310-win32.whl", hash = "sha256:6dd97011efc8bf51d6793a82292419eba2c71cf8e7250cfac03bba284454abc1"}, - {file = "pywin32-310-cp310-cp310-win_amd64.whl", hash = "sha256:c3e78706e4229b915a0821941a84e7ef420bf2b77e08c9dae3c76fd03fd2ae3d"}, - {file = "pywin32-310-cp310-cp310-win_arm64.whl", hash = "sha256:33babed0cf0c92a6f94cc6cc13546ab24ee13e3e800e61ed87609ab91e4c8213"}, - {file = "pywin32-310-cp311-cp311-win32.whl", hash = "sha256:1e765f9564e83011a63321bb9d27ec456a0ed90d3732c4b2e312b855365ed8bd"}, - {file = "pywin32-310-cp311-cp311-win_amd64.whl", hash = "sha256:126298077a9d7c95c53823934f000599f66ec9296b09167810eb24875f32689c"}, - {file = "pywin32-310-cp311-cp311-win_arm64.whl", hash = "sha256:19ec5fc9b1d51c4350be7bb00760ffce46e6c95eaf2f0b2f1150657b1a43c582"}, - {file = "pywin32-310-cp312-cp312-win32.whl", hash = "sha256:8a75a5cc3893e83a108c05d82198880704c44bbaee4d06e442e471d3c9ea4f3d"}, - {file = "pywin32-310-cp312-cp312-win_amd64.whl", hash = "sha256:bf5c397c9a9a19a6f62f3fb821fbf36cac08f03770056711f765ec1503972060"}, - {file = "pywin32-310-cp312-cp312-win_arm64.whl", hash = "sha256:2349cc906eae872d0663d4d6290d13b90621eaf78964bb1578632ff20e152966"}, - {file = "pywin32-310-cp313-cp313-win32.whl", hash = "sha256:5d241a659c496ada3253cd01cfaa779b048e90ce4b2b38cd44168ad555ce74ab"}, - {file = "pywin32-310-cp313-cp313-win_amd64.whl", hash = "sha256:667827eb3a90208ddbdcc9e860c81bde63a135710e21e4cb3348968e4bd5249e"}, - {file = "pywin32-310-cp313-cp313-win_arm64.whl", hash = "sha256:e308f831de771482b7cf692a1f308f8fca701b2d8f9dde6cc440c7da17e47b33"}, - {file = "pywin32-310-cp38-cp38-win32.whl", hash = "sha256:0867beb8addefa2e3979d4084352e4ac6e991ca45373390775f7084cc0209b9c"}, - {file = "pywin32-310-cp38-cp38-win_amd64.whl", hash = "sha256:30f0a9b3138fb5e07eb4973b7077e1883f558e40c578c6925acc7a94c34eaa36"}, - {file = "pywin32-310-cp39-cp39-win32.whl", hash = "sha256:851c8d927af0d879221e616ae1f66145253537bbdd321a77e8ef701b443a9a1a"}, - {file = "pywin32-310-cp39-cp39-win_amd64.whl", hash = "sha256:96867217335559ac619f00ad70e513c0fcf84b8a3af9fc2bba3b59b97da70475"}, + {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, + {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, + {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, + {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, + {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, + {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, + {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, + {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, + {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, + {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, + {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, + {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, + {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, + {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, + {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, + {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, + {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, + {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, + {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, + {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, ] [[package]] name = "pyyaml" -version = "6.0.2" +version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, + {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, + {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, + {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, + {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, + {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, + {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198"}, + {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0"}, + {file = "pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69"}, + {file = "pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e"}, + {file = "pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e"}, + {file = "pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00"}, + {file = "pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a"}, + {file = "pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4"}, + {file = "pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b"}, + {file = "pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196"}, + {file = "pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c"}, + {file = "pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e"}, + {file = "pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea"}, + {file = "pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b"}, + {file = "pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8"}, + {file = "pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5"}, + {file = "pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6"}, + {file = "pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be"}, + {file = "pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c"}, + {file = "pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac"}, + {file = "pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788"}, + {file = "pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764"}, + {file = "pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac"}, + {file = "pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3"}, + {file = "pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702"}, + {file = "pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065"}, + {file = "pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9"}, + {file = "pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da"}, + {file = "pyyaml-6.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5"}, + {file = "pyyaml-6.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926"}, + {file = "pyyaml-6.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7"}, + {file = "pyyaml-6.0.3-cp39-cp39-win32.whl", hash = "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0"}, + {file = "pyyaml-6.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007"}, + {file = "pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f"}, ] [[package]] @@ -1552,118 +1852,139 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" -version = "2024.11.6" +version = "2025.9.18" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, - {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, - {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, - {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, - {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, - {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, - {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, - {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, - {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, - {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, - {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, - {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, - {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, - {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:12296202480c201c98a84aecc4d210592b2f55e200a1d193235c4db92b9f6788"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:220381f1464a581f2ea988f2220cf2a67927adcef107d47d6897ba5a2f6d51a4"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87f681bfca84ebd265278b5daa1dcb57f4db315da3b5d044add7c30c10442e61"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34d674cbba70c9398074c8a1fcc1a79739d65d1105de2a3c695e2b05ea728251"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:385c9b769655cb65ea40b6eea6ff763cbb6d69b3ffef0b0db8208e1833d4e746"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8900b3208e022570ae34328712bef6696de0804c122933414014bae791437ab2"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c204e93bf32cd7a77151d44b05eb36f469d0898e3fba141c026a26b79d9914a0"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3acc471d1dd7e5ff82e6cacb3b286750decd949ecd4ae258696d04f019817ef8"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6479d5555122433728760e5f29edb4c2b79655a8deb681a141beb5c8a025baea"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:431bd2a8726b000eb6f12429c9b438a24062a535d06783a93d2bcbad3698f8a8"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0cc3521060162d02bd36927e20690129200e5ac9d2c6d32b70368870b122db25"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a021217b01be2d51632ce056d7a837d3fa37c543ede36e39d14063176a26ae29"}, + {file = "regex-2025.9.18-cp310-cp310-win32.whl", hash = "sha256:4a12a06c268a629cb67cc1d009b7bb0be43e289d00d5111f86a2efd3b1949444"}, + {file = "regex-2025.9.18-cp310-cp310-win_amd64.whl", hash = "sha256:47acd811589301298c49db2c56bde4f9308d6396da92daf99cba781fa74aa450"}, + {file = "regex-2025.9.18-cp310-cp310-win_arm64.whl", hash = "sha256:16bd2944e77522275e5ee36f867e19995bcaa533dcb516753a26726ac7285442"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:51076980cd08cd13c88eb7365427ae27f0d94e7cebe9ceb2bb9ffdae8fc4d82a"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:828446870bd7dee4e0cbeed767f07961aa07f0ea3129f38b3ccecebc9742e0b8"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28821d5637866479ec4cc23b8c990f5bc6dd24e5e4384ba4a11d38a526e1414"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:726177ade8e481db669e76bf99de0b278783be8acd11cef71165327abd1f170a"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5cca697da89b9f8ea44115ce3130f6c54c22f541943ac8e9900461edc2b8bd4"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dfbde38f38004703c35666a1e1c088b778e35d55348da2b7b278914491698d6a"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f2f422214a03fab16bfa495cfec72bee4aaa5731843b771860a471282f1bf74f"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a295916890f4df0902e4286bc7223ee7f9e925daa6dcdec4192364255b70561a"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5db95ff632dbabc8c38c4e82bf545ab78d902e81160e6e455598014f0abe66b9"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb967eb441b0f15ae610b7069bdb760b929f267efbf522e814bbbfffdf125ce2"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f04d2f20da4053d96c08f7fde6e1419b7ec9dbcee89c96e3d731fca77f411b95"}, + {file = "regex-2025.9.18-cp311-cp311-win32.whl", hash = "sha256:895197241fccf18c0cea7550c80e75f185b8bd55b6924fcae269a1a92c614a07"}, + {file = "regex-2025.9.18-cp311-cp311-win_amd64.whl", hash = "sha256:7e2b414deae99166e22c005e154a5513ac31493db178d8aec92b3269c9cce8c9"}, + {file = "regex-2025.9.18-cp311-cp311-win_arm64.whl", hash = "sha256:fb137ec7c5c54f34a25ff9b31f6b7b0c2757be80176435bf367111e3f71d72df"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:436e1b31d7efd4dcd52091d076482031c611dde58bf9c46ca6d0a26e33053a7e"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c190af81e5576b9c5fdc708f781a52ff20f8b96386c6e2e0557a78402b029f4a"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e4121f1ce2b2b5eec4b397cc1b277686e577e658d8f5870b7eb2d726bd2300ab"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:300e25dbbf8299d87205e821a201057f2ef9aa3deb29caa01cd2cac669e508d5"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b47fcf9f5316c0bdaf449e879407e1b9937a23c3b369135ca94ebc8d74b1742"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:57a161bd3acaa4b513220b49949b07e252165e6b6dc910ee7617a37ff4f5b425"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f130c3a7845ba42de42f380fff3c8aebe89a810747d91bcf56d40a069f15352"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f96fa342b6f54dcba928dd452e8d8cb9f0d63e711d1721cd765bb9f73bb048d"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f0d676522d68c207828dcd01fb6f214f63f238c283d9f01d85fc664c7c85b56"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:40532bff8a1a0621e7903ae57fce88feb2e8a9a9116d341701302c9302aef06e"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:039f11b618ce8d71a1c364fdee37da1012f5a3e79b1b2819a9f389cd82fd6282"}, + {file = "regex-2025.9.18-cp312-cp312-win32.whl", hash = "sha256:e1dd06f981eb226edf87c55d523131ade7285137fbde837c34dc9d1bf309f459"}, + {file = "regex-2025.9.18-cp312-cp312-win_amd64.whl", hash = "sha256:3d86b5247bf25fa3715e385aa9ff272c307e0636ce0c9595f64568b41f0a9c77"}, + {file = "regex-2025.9.18-cp312-cp312-win_arm64.whl", hash = "sha256:032720248cbeeae6444c269b78cb15664458b7bb9ed02401d3da59fe4d68c3a5"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a40f929cd907c7e8ac7566ac76225a77701a6221bca937bdb70d56cb61f57b2"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c90471671c2cdf914e58b6af62420ea9ecd06d1554d7474d50133ff26ae88feb"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a351aff9e07a2dabb5022ead6380cff17a4f10e4feb15f9100ee56c4d6d06af"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc4b8e9d16e20ddfe16430c23468a8707ccad3365b06d4536142e71823f3ca29"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b8cdbddf2db1c5e80338ba2daa3cfa3dec73a46fff2a7dda087c8efbf12d62f"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a276937d9d75085b2c91fb48244349c6954f05ee97bba0963ce24a9d915b8b68"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92a8e375ccdc1256401c90e9dc02b8642894443d549ff5e25e36d7cf8a80c783"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0dc6893b1f502d73037cf807a321cdc9be29ef3d6219f7970f842475873712ac"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a61e85bfc63d232ac14b015af1261f826260c8deb19401c0597dbb87a864361e"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1ef86a9ebc53f379d921fb9a7e42b92059ad3ee800fcd9e0fe6181090e9f6c23"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d3bc882119764ba3a119fbf2bd4f1b47bc56c1da5d42df4ed54ae1e8e66fdf8f"}, + {file = "regex-2025.9.18-cp313-cp313-win32.whl", hash = "sha256:3810a65675845c3bdfa58c3c7d88624356dd6ee2fc186628295e0969005f928d"}, + {file = "regex-2025.9.18-cp313-cp313-win_amd64.whl", hash = "sha256:16eaf74b3c4180ede88f620f299e474913ab6924d5c4b89b3833bc2345d83b3d"}, + {file = "regex-2025.9.18-cp313-cp313-win_arm64.whl", hash = "sha256:4dc98ba7dd66bd1261927a9f49bd5ee2bcb3660f7962f1ec02617280fc00f5eb"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:fe5d50572bc885a0a799410a717c42b1a6b50e2f45872e2b40f4f288f9bce8a2"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b9d9a2d6cda6621551ca8cf7a06f103adf72831153f3c0d982386110870c4d3"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:13202e4c4ac0ef9a317fff817674b293c8f7e8c68d3190377d8d8b749f566e12"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874ff523b0fecffb090f80ae53dc93538f8db954c8bb5505f05b7787ab3402a0"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d13ab0490128f2bb45d596f754148cd750411afc97e813e4b3a61cf278a23bb6"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05440bc172bc4b4b37fb9667e796597419404dbba62e171e1f826d7d2a9ebcef"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5514b8e4031fdfaa3d27e92c75719cbe7f379e28cacd939807289bce76d0e35a"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:65d3c38c39efce73e0d9dc019697b39903ba25b1ad45ebbd730d2cf32741f40d"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ae77e447ebc144d5a26d50055c6ddba1d6ad4a865a560ec7200b8b06bc529368"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3ef8cf53dc8df49d7e28a356cf824e3623764e9833348b655cfed4524ab8a90"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9feb29817df349c976da9a0debf775c5c33fc1c8ad7b9f025825da99374770b7"}, + {file = "regex-2025.9.18-cp313-cp313t-win32.whl", hash = "sha256:168be0d2f9b9d13076940b1ed774f98595b4e3c7fc54584bba81b3cc4181742e"}, + {file = "regex-2025.9.18-cp313-cp313t-win_amd64.whl", hash = "sha256:d59ecf3bb549e491c8104fea7313f3563c7b048e01287db0a90485734a70a730"}, + {file = "regex-2025.9.18-cp313-cp313t-win_arm64.whl", hash = "sha256:dbef80defe9fb21310948a2595420b36c6d641d9bea4c991175829b2cc4bc06a"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c6db75b51acf277997f3adcd0ad89045d856190d13359f15ab5dda21581d9129"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8f9698b6f6895d6db810e0bda5364f9ceb9e5b11328700a90cae573574f61eea"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29cd86aa7cb13a37d0f0d7c21d8d949fe402ffa0ea697e635afedd97ab4b69f1"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c9f285a071ee55cd9583ba24dde006e53e17780bb309baa8e4289cd472bcc47"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5adf266f730431e3be9021d3e5b8d5ee65e563fec2883ea8093944d21863b379"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1137cabc0f38807de79e28d3f6e3e3f2cc8cfb26bead754d02e6d1de5f679203"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cc9e5525cada99699ca9223cce2d52e88c52a3d2a0e842bd53de5497c604164"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bbb9246568f72dce29bcd433517c2be22c7791784b223a810225af3b50d1aafb"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6a52219a93dd3d92c675383efff6ae18c982e2d7651c792b1e6d121055808743"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:ae9b3840c5bd456780e3ddf2f737ab55a79b790f6409182012718a35c6d43282"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d488c236ac497c46a5ac2005a952c1a0e22a07be9f10c3e735bc7d1209a34773"}, + {file = "regex-2025.9.18-cp314-cp314-win32.whl", hash = "sha256:0c3506682ea19beefe627a38872d8da65cc01ffa25ed3f2e422dffa1474f0788"}, + {file = "regex-2025.9.18-cp314-cp314-win_amd64.whl", hash = "sha256:57929d0f92bebb2d1a83af372cd0ffba2263f13f376e19b1e4fa32aec4efddc3"}, + {file = "regex-2025.9.18-cp314-cp314-win_arm64.whl", hash = "sha256:6a4b44df31d34fa51aa5c995d3aa3c999cec4d69b9bd414a8be51984d859f06d"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b176326bcd544b5e9b17d6943f807697c0cb7351f6cfb45bf5637c95ff7e6306"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0ffd9e230b826b15b369391bec167baed57c7ce39efc35835448618860995946"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec46332c41add73f2b57e2f5b642f991f6b15e50e9f86285e08ffe3a512ac39f"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b80fa342ed1ea095168a3f116637bd1030d39c9ff38dc04e54ef7c521e01fc95"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4d97071c0ba40f0cf2a93ed76e660654c399a0a04ab7d85472239460f3da84b"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0ac936537ad87cef9e0e66c5144484206c1354224ee811ab1519a32373e411f3"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dec57f96d4def58c422d212d414efe28218d58537b5445cf0c33afb1b4768571"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48317233294648bf7cd068857f248e3a57222259a5304d32c7552e2284a1b2ad"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:274687e62ea3cf54846a9b25fc48a04459de50af30a7bd0b61a9e38015983494"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a78722c86a3e7e6aadf9579e3b0ad78d955f2d1f1a8ca4f67d7ca258e8719d4b"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:06104cd203cdef3ade989a1c45b6215bf42f8b9dd705ecc220c173233f7cba41"}, + {file = "regex-2025.9.18-cp314-cp314t-win32.whl", hash = "sha256:2e1eddc06eeaffd249c0adb6fafc19e2118e6308c60df9db27919e96b5656096"}, + {file = "regex-2025.9.18-cp314-cp314t-win_amd64.whl", hash = "sha256:8620d247fb8c0683ade51217b459cb4a1081c0405a3072235ba43a40d355c09a"}, + {file = "regex-2025.9.18-cp314-cp314t-win_arm64.whl", hash = "sha256:b7531a8ef61de2c647cdf68b3229b071e46ec326b3138b2180acb4275f470b01"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3dbcfcaa18e9480669030d07371713c10b4f1a41f791ffa5cb1a99f24e777f40"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1e85f73ef7095f0380208269055ae20524bfde3f27c5384126ddccf20382a638"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9098e29b3ea4ffffeade423f6779665e2a4f8db64e699c0ed737ef0db6ba7b12"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90b6b7a2d0f45b7ecaaee1aec6b362184d6596ba2092dd583ffba1b78dd0231c"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c81b892af4a38286101502eae7aec69f7cd749a893d9987a92776954f3943408"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3b524d010973f2e1929aeb635418d468d869a5f77b52084d9f74c272189c251d"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b498437c026a3d5d0be0020023ff76d70ae4d77118e92f6f26c9d0423452446"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0716e4d6e58853d83f6563f3cf25c281ff46cf7107e5f11879e32cb0b59797d9"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:065b6956749379d41db2625f880b637d4acc14c0a4de0d25d609a62850e96d36"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d4a691494439287c08ddb9b5793da605ee80299dd31e95fa3f323fac3c33d9d4"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ef8d10cc0989565bcbe45fb4439f044594d5c2b8919d3d229ea2c4238f1d55b0"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4baeb1b16735ac969a7eeecc216f1f8b7caf60431f38a2671ae601f716a32d25"}, + {file = "regex-2025.9.18-cp39-cp39-win32.whl", hash = "sha256:8e5f41ad24a1e0b5dfcf4c4e5d9f5bd54c895feb5708dd0c1d0d35693b24d478"}, + {file = "regex-2025.9.18-cp39-cp39-win_amd64.whl", hash = "sha256:50e8290707f2fb8e314ab3831e594da71e062f1d623b05266f8cfe4db4949afd"}, + {file = "regex-2025.9.18-cp39-cp39-win_arm64.whl", hash = "sha256:039a9d7195fd88c943d7c777d4941e8ef736731947becce773c31a1009cb3c35"}, + {file = "regex-2025.9.18.tar.gz", hash = "sha256:c5ba23274c61c6fef447ba6a39333297d0c247f53059dba0bca415cac511edc4"}, ] [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [package.dependencies] @@ -1678,129 +1999,167 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rpds-py" -version = "0.25.1" +version = "0.27.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "rpds_py-0.25.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9"}, - {file = "rpds_py-0.25.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da"}, - {file = "rpds_py-0.25.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54"}, - {file = "rpds_py-0.25.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2"}, - {file = "rpds_py-0.25.1-cp310-cp310-win32.whl", hash = "sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24"}, - {file = "rpds_py-0.25.1-cp310-cp310-win_amd64.whl", hash = "sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d"}, - {file = "rpds_py-0.25.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd"}, - {file = "rpds_py-0.25.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d"}, - {file = "rpds_py-0.25.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042"}, - {file = "rpds_py-0.25.1-cp311-cp311-win32.whl", hash = "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4"}, - {file = "rpds_py-0.25.1-cp311-cp311-win_arm64.whl", hash = "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c"}, - {file = "rpds_py-0.25.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea"}, - {file = "rpds_py-0.25.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd"}, - {file = "rpds_py-0.25.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb"}, - {file = "rpds_py-0.25.1-cp312-cp312-win32.whl", hash = "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_amd64.whl", hash = "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192"}, - {file = "rpds_py-0.25.1-cp312-cp312-win_arm64.whl", hash = "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559"}, - {file = "rpds_py-0.25.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325"}, - {file = "rpds_py-0.25.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98"}, - {file = "rpds_py-0.25.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd"}, - {file = "rpds_py-0.25.1-cp313-cp313-win32.whl", hash = "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500"}, - {file = "rpds_py-0.25.1-cp313-cp313-win_arm64.whl", hash = "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129"}, - {file = "rpds_py-0.25.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194"}, - {file = "rpds_py-0.25.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72"}, - {file = "rpds_py-0.25.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win32.whl", hash = "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523"}, - {file = "rpds_py-0.25.1-cp313-cp313t-win_amd64.whl", hash = "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd"}, - {file = "rpds_py-0.25.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9"}, - {file = "rpds_py-0.25.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451"}, - {file = "rpds_py-0.25.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f"}, - {file = "rpds_py-0.25.1-cp39-cp39-win32.whl", hash = "sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449"}, - {file = "rpds_py-0.25.1-cp39-cp39-win_amd64.whl", hash = "sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11"}, - {file = "rpds_py-0.25.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf"}, - {file = "rpds_py-0.25.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992"}, - {file = "rpds_py-0.25.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793"}, - {file = "rpds_py-0.25.1.tar.gz", hash = "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3"}, + {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"}, + {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1"}, + {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8"}, + {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9"}, + {file = "rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4"}, + {file = "rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881"}, + {file = "rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a"}, + {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9"}, + {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948"}, + {file = "rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15"}, + {file = "rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90"}, + {file = "rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a"}, + {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1"}, + {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998"}, + {file = "rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594"}, + {file = "rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b"}, + {file = "rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d"}, + {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2"}, + {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002"}, + {file = "rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83"}, + {file = "rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228"}, + {file = "rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21"}, + {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd"}, + {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688"}, + {file = "rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334"}, + {file = "rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9"}, + {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212"}, + {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675"}, + {file = "rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456"}, + {file = "rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2"}, + {file = "rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48"}, + {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb"}, + {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a"}, + {file = "rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527"}, + {file = "rpds_py-0.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e"}, + {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec"}, + {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b"}, + {file = "rpds_py-0.27.1-cp39-cp39-win32.whl", hash = "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52"}, + {file = "rpds_py-0.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b"}, + {file = "rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6"}, + {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c"}, + {file = "rpds_py-0.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859"}, + {file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"}, ] [[package]] @@ -1860,14 +2219,14 @@ files = [ [[package]] name = "soupsieve" -version = "2.7" +version = "2.8" description = "A modern CSS selector implementation for Beautiful Soup." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] files = [ - {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, - {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, + {file = "soupsieve-2.8-py3-none-any.whl", hash = "sha256:0cc76456a30e20f5d7f2e14a98a4ae2ee4e5abdc7c5ea0aafe795f344bc7984c"}, + {file = "soupsieve-2.8.tar.gz", hash = "sha256:e2dd4a40a628cb5f28f6d4b0db8800b8f581b65bb380b97de22ba5ca8d72572f"}, ] [[package]] @@ -1999,14 +2358,14 @@ typing_extensions = ">=4.14.0" [[package]] name = "typing-extensions" -version = "4.14.0" +version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"}, - {file = "typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] [[package]] @@ -2023,21 +2382,21 @@ files = [ [[package]] name = "urllib3" -version = "2.5.0" +version = "2.6.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, - {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, + {file = "urllib3-2.6.0-py3-none-any.whl", hash = "sha256:c90f7a39f716c572c4e3e58509581ebd83f9b59cced005b7db7ad2d22b0db99f"}, + {file = "urllib3-2.6.0.tar.gz", hash = "sha256:cb9bcef5a4b345d5da5d145dc3e30834f58e8018828cbc724d30b4cb7d4d49f1"}, ] [package.extras] -brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "validators" @@ -2086,4 +2445,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<=3.13" -content-hash = "c5239f0416a42725c120463e60fb2e556d90812da2d11c5615027f5b4be512bb" +content-hash = "a9e23606801bb83f85f7d6c4a823adca5188d05fcf67cbf03e1496da67dba4a5" diff --git a/pyproject.toml b/pyproject.toml index bf4ea59..1bb5d2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,49 +1,49 @@ -[project] +[tool.poetry] name = "somef_core" version = "0.0.1" -description = "SOftware Metadata Extraction Framework (CORE): A tool for automatically extracting relevant software metadata from readme files and package files." -authors = [ - { name = "Daniel Garijo", email = "daniel.garijo@upm.es" } -] +description = "SOftware Metadata Extraction Framework (CORE): A tool for automatically extracting relevant software metadata from a source code repository (README, package files, etc)." +authors = ["Daniel Garijo "] +readme = "README.md" packages = [ { include = "somef_core", from = "src" } ] -requires-python = ">=3.9,<=3.13" classifiers = [ "Programming Language :: Python :: 3.10", "Operating System :: OS Independent", "License :: OSI Approved :: MIT License", "Topic :: Software Development :: Libraries :: Python Modules" ] -urls = { homepage = "https://github.com/SciCodes/somef-core" } - -readme = "README.md" - -dependencies = [ - "bs4 >=0.0.1", - "click >=8.1.7", - "click-option-group >=0.5.6", - "matplotlib >=3.8.2", - "nltk >=3.9.0", - "numpy >=1.26.3", - "pandas >=2.1.4", - "textblob >=0.17.1", - "validators >=0.22.0", - "scipy >=1.11.4", - "inflect >=7.0.0", - "contractions >=0.1.73", - "chardet >=5.2.0", - "pytest >=7.4.4", - "bibtexparser >=1.4.1", - "nbformat >=5.9.2", - "markdown >=3.5.2", - "requests >=2.31.0", - "pyyaml >=6.0.2", - "lxml >=5.1.0", - "tomli >=2.0.1" -] + +[tool.poetry.urls] +homepage = "https://github.com/SciCodes/somef-core" -[project.scripts] +[tool.poetry.dependencies] + python = ">=3.9,<=3.13" + bs4 = "^0.0.1" + click = "^8.1.7" + click-option-group = "^0.5.6" + matplotlib = "^3.8.2" + nltk = "^3.9.0" + numpy = "^1.26.3" + pandas = "^2.1.4" + textblob = "^0.17.1" + validators = "^0.22.0" + scipy = "^1.11.4" + inflect = "^7.0.0" + contractions = "^0.1.73" + chardet = "^5.2.0" + pytest = "^7.4.4" + bibtexparser = "^1.4.1" + nbformat = "^5.9.2" + markdown = "^3.5.2" + markdown-it-py = "^3.0" + requests = "^2.31.0" + pyyaml = "^6.0.2" + lxml = "^5.1.0" + tomli = "^2.0.1" + + +[tool.poetry.scripts] somef_core = "somef_core.__main__:cli" [build-system] diff --git a/pytest 2.ini b/pytest 2.ini new file mode 100644 index 0000000..2f80c74 --- /dev/null +++ b/pytest 2.ini @@ -0,0 +1,7 @@ +[pytest] +testpaths = somef/src/somef/test +python_files = test_*.py +python_classes = Test* +python_functions = test_* + +norecursedirs = test_data .git .venv __pycache__ *.egg-info diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..2f80c74 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,7 @@ +[pytest] +testpaths = somef/src/somef/test +python_files = test_*.py +python_classes = Test* +python_functions = test_* + +norecursedirs = test_data .git .venv __pycache__ *.egg-info diff --git a/src/somef_core/__init__.py b/src/somef_core/__init__.py index 5f1d2cc..3f3e589 100644 --- a/src/somef_core/__init__.py +++ b/src/somef_core/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -__version__ = "0.0.1" +__version__ = "0.9.13" diff --git a/src/somef_core/__main__.py b/src/somef_core/__main__.py index 7e20e9b..9df797c 100644 --- a/src/somef_core/__main__.py +++ b/src/somef_core/__main__.py @@ -33,10 +33,10 @@ def configure(auto, base_uri): configuration.update_base_uri(base_uri) else: authorization = click.prompt("Authorization", default="") - description = None - invocation = None - installation = None - citation = None + description = click.prompt("Documentation classifier model file", default=configuration.default_description) + invocation = click.prompt("Invocation classifier model file", default=configuration.default_invocation) + installation = click.prompt("Installation classifier model file", default=configuration.default_installation) + citation = click.prompt("Citation classifier model file", default=configuration.default_citation) base_uri = click.prompt("Base URI for RDF generation", default=base_uri) # configuration.configure() configuration.configure(authorization, description, invocation, installation, citation, base_uri) @@ -157,8 +157,30 @@ def configure(auto, base_uri): default=True, help="""SOMEF will ignore the contents of all files within folders named test (True by default)""" ) -def describe(**kwargs): +@click.option( + "--requirements_all", + "-all", + is_flag=True, + default=False, + help="Export all detected requirements, including text and libraries (default)." +) +@click.option( + "--requirements_v", + "-v", + is_flag=True, + default=False, + help="Export only requirements from structured sources (pom.xml, requirements.txt, etc.)" +) +def describe(requirements_v, requirements_all, **kwargs): # import so missing packages get installed when appropriate + if requirements_v: + kwargs["requirements_mode"] = "v" + elif requirements_all: + kwargs["requirements_mode"] = "all" + else: + kwargs["requirements_mode"] = "all" + from . import somef_cli somef_cli.run_cli(**kwargs) - click.secho(f"Success", fg="green") \ No newline at end of file + click.secho(f"Success", fg="green") + \ No newline at end of file diff --git a/src/somef_core/configuration.py b/src/somef_core/configuration.py index 177cf2e..d0d4004 100644 --- a/src/somef_core/configuration.py +++ b/src/somef_core/configuration.py @@ -3,8 +3,16 @@ import json import sys import logging + from .utils import constants +path = Path(__file__).parent.absolute() +default_description = os.path.join(str(path), "models", "description.p") +default_invocation = os.path.join(str(path), "models", "invocation.p") +default_installation = os.path.join(str(path), "models", "installation.p") +default_citation = os.path.join(str(path), "models", "citation.p") + + def get_configuration_file(): """ Function that retrieves the configuration file @@ -39,11 +47,12 @@ def update_base_uri(base_uri): credentials_file.chmod(0o600) json.dump(data, fh) + def configure(authorization="", - description=None, - invocation=None, - installation=None, - citation=None, + description=default_description, + invocation=default_invocation, + installation=default_installation, + citation=default_citation, base_uri=constants.CONF_DEFAULT_BASE_URI): """ Function to configure the main program""" import nltk diff --git a/src/somef_core/export/json_export.py b/src/somef_core/export/json_export.py index 7fed51d..547344c 100644 --- a/src/somef_core/export/json_export.py +++ b/src/somef_core/export/json_export.py @@ -5,6 +5,7 @@ from dateutil import parser as date_parser from ..utils import constants from ..regular_expressions import detect_license_spdx,extract_scholarly_article_natural, extract_scholarly_article_properties +from typing import List, Dict def save_json_output(repo_data, out_path, missing, pretty=False): """ @@ -31,7 +32,7 @@ def save_json_output(repo_data, out_path, missing, pretty=False): json.dump(repo_data, output) -def save_codemeta_output(repo_data, outfile, pretty=False): +def save_codemeta_output(repo_data, outfile, pretty=False, requirements_mode='all'): """ Function that saves a Codemeta JSONLD file with a summary of the results @@ -40,6 +41,7 @@ def save_codemeta_output(repo_data, outfile, pretty=False): @param repo_data: JSON with the results to translate to Codemeta @param outfile: path where to save the codemeta file @param pretty: option to show the JSON results in a nice format + @param requriments_mode: option to show all requriments or just machine readable """ def format_date(date_string): date_object = date_parser.parse(date_string) @@ -76,9 +78,40 @@ def format_date(date_string): descriptions_text = [] if descriptions is not None: - descriptions.sort(key=lambda x: (x[constants.PROP_CONFIDENCE] + (1 if x[constants.PROP_TECHNIQUE] == constants.GITHUB_API else 0)), - reverse=True) - descriptions_text = [x[constants.PROP_RESULT][constants.PROP_VALUE] for x in descriptions] + + # priority descriptions: Codemeta, without codemeta but confidence 1, rest + codemeta_desc = [d for d in descriptions if d.get("technique") == "code_parser" and "codemeta.json" in d.get("source", "")] + github_desc = [d for d in descriptions if d.get("technique") == constants.GITHUB_API] + readme_desc = [d for d in descriptions if d.get("technique") not in ("code_parser", constants.GITHUB_API)] + + if codemeta_desc: + # If codemeta just these + selected = codemeta_desc + elif github_desc: + # whitout codemeta, but we have descripciont with confidence 1 + threshold_1 = [d for d in github_desc if d.get("confidence", 0) == 1] + selected = threshold_1 if threshold_1 else github_desc + else: + # Rest of descriptions + selected = sorted(readme_desc, key=lambda x: x.get("confidence", 0), reverse=True)[:1] + + flat_descriptions = [] + for d in selected: + value = d[constants.PROP_RESULT][constants.PROP_VALUE] + if isinstance(value, list): + for v in value: + if v not in flat_descriptions: + flat_descriptions.append(v) + else: + if value not in flat_descriptions: + flat_descriptions.append(value) + + descriptions_text = flat_descriptions + + # descriptions_text = [d[constants.PROP_RESULT][constants.PROP_VALUE] for d in selected] + # descriptions.sort(key=lambda x: (x[constants.PROP_CONFIDENCE] + (1 if x[constants.PROP_TECHNIQUE] == constants.GITHUB_API else 0)), + # reverse=True) + # descriptions_text = [x[constants.PROP_RESULT][constants.PROP_VALUE] for x in descriptions] codemeta_output = { @@ -123,25 +156,29 @@ def format_date(date_string): l_result["identifier"] = constants.SPDX_BASE + l[constants.PROP_RESULT][constants.PROP_SPDX_ID] l_result["spdx_id"] = l[constants.PROP_RESULT][constants.PROP_SPDX_ID] - codemeta_output["license"] = l_result + codemeta_output[constants.CAT_CODEMETA_LICENSE] = l_result if code_repository is not None: - codemeta_output["codeRepository"] = code_repository - codemeta_output["issueTracker"] = code_repository + "/issues" + codemeta_output[constants.CAT_CODEMETA_CODEREPOSITORY] = code_repository + codemeta_output[constants.CAT_CODEMETA_ISSUETRACKER] = code_repository + "/issues" if constants.CAT_DATE_CREATED in repo_data: - codemeta_output["dateCreated"] = format_date(repo_data[constants.CAT_DATE_CREATED][0][constants.PROP_RESULT][constants.PROP_VALUE]) + value = repo_data[constants.CAT_DATE_CREATED][0][constants.PROP_RESULT][constants.PROP_VALUE] + if value: + codemeta_output[constants.CAT_CODEMETA_DATECREATED] = format_date(value) if constants.CAT_DATE_UPDATED in repo_data: - codemeta_output["dateModified"] = format_date(repo_data[constants.CAT_DATE_UPDATED][0][constants.PROP_RESULT][constants.PROP_VALUE]) + value = repo_data[constants.CAT_DATE_UPDATED][0][constants.PROP_RESULT][constants.PROP_VALUE] + if value: + codemeta_output[constants.CAT_CODEMETA_DATEMODIFIED] = format_date(value) if constants.CAT_DOWNLOAD_URL in repo_data: - codemeta_output["downloadUrl"] = repo_data[constants.CAT_DOWNLOAD_URL][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_DOWNLOADURL] = repo_data[constants.CAT_DOWNLOAD_URL][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_NAME in repo_data: - codemeta_output["name"] = repo_data[constants.CAT_NAME][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_NAME] = repo_data[constants.CAT_NAME][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_LOGO in repo_data: - codemeta_output["logo"] = repo_data[constants.CAT_LOGO][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_LOGO] = repo_data[constants.CAT_LOGO][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_KEYWORDS in repo_data: - codemeta_output["keywords"] = repo_data[constants.CAT_KEYWORDS][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_KEYWORDS] = repo_data[constants.CAT_KEYWORDS][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_PROGRAMMING_LANGUAGES in repo_data: # Calculate the total code size of all the programming languages - codemeta_output["programmingLanguage"] = [] + codemeta_output[constants.CAT_CODEMETA_PROGRAMMINGLANGUAGE] = [] language_data = repo_data.get(constants.CAT_PROGRAMMING_LANGUAGES, []) total_size = 0 for item in language_data: @@ -154,38 +191,54 @@ def format_date(date_string): result = item.get(constants.PROP_RESULT, {}) size = result.get(constants.PROP_SIZE) value = result.get(constants.PROP_VALUE) - if value not in codemeta_output["programmingLanguage"]: + if value not in codemeta_output[constants.CAT_CODEMETA_PROGRAMMINGLANGUAGE]: if size is not None and value is not None and total_size > 0: percentage = (size / total_size) * 100 if percentage > constants.MINIMUM_PERCENTAGE_LANGUAGE_PROGRAMMING: - codemeta_output["programmingLanguage"].append(value) + codemeta_output[constants.CAT_CODEMETA_PROGRAMMINGLANGUAGE].append(value) elif size is None: # when size is not available, it comes from the parsers - codemeta_output["programmingLanguage"].append(value) + codemeta_output[constants.CAT_CODEMETA_PROGRAMMINGLANGUAGE].append(value) if constants.CAT_REQUIREMENTS in repo_data: - # codemeta_output["softwareRequirements"] = [x[constants.PROP_RESULT][constants.PROP_VALUE] for x in repo_data[constants.CAT_REQUIREMENTS]] - code_parser_requirements = [ - { - "name": x[constants.PROP_RESULT].get(constants.PROP_NAME) - if x[constants.PROP_RESULT].get(constants.PROP_NAME) - else x[constants.PROP_RESULT].get(constants.PROP_VALUE), - "version": x[constants.PROP_RESULT].get(constants.PROP_VERSION) - } - for x in repo_data[constants.CAT_REQUIREMENTS] - if x.get(constants.PROP_TECHNIQUE) == constants.TECHNIQUE_CODE_CONFIG_PARSER - ] + structured_sources = ["pom.xml", "requirements.txt", "setup.py", "environment.yml"] + + code_parser_requirements = [] + seen_structured = set() + for x in repo_data[constants.CAT_REQUIREMENTS]: + if x.get(constants.PROP_TECHNIQUE) == constants.TECHNIQUE_CODE_CONFIG_PARSER: + source = x.get("source", "") + if any(src in source for src in structured_sources): + name = x[constants.PROP_RESULT].get(constants.PROP_NAME) or x[constants.PROP_RESULT].get(constants.PROP_VALUE) + version = x[constants.PROP_RESULT].get(constants.PROP_VERSION) + key = f"{name.strip()}|{version.strip() if version else ''}" + if key not in seen_structured: + entry = {"name": name.strip()} + if version: + entry["version"] = version.strip() + code_parser_requirements.append(entry) + seen_structured.add(key) + + other_requirements = [] + seen_text = set() + for x in repo_data[constants.CAT_REQUIREMENTS]: + if not ( + x.get(constants.PROP_TECHNIQUE) == constants.TECHNIQUE_CODE_CONFIG_PARSER + and x.get("source") is not None + and any(src in x["source"] for src in structured_sources) + ): + value = x[constants.PROP_RESULT].get(constants.PROP_VALUE, "").strip().replace("\n", " ") + normalized = " ".join(value.split()) + if normalized not in seen_text: + other_requirements.append(value) + seen_text.add(normalized) + + if requirements_mode == "v": + codemeta_output[constants.CAT_CODEMETA_SOFTWAREREQUIREMENTS] = code_parser_requirements + else: + codemeta_output[constants.CAT_CODEMETA_SOFTWAREREQUIREMENTS] = code_parser_requirements + other_requirements - other_requirements = [ - x[constants.PROP_RESULT][constants.PROP_VALUE] - for x in repo_data[constants.CAT_REQUIREMENTS] - if x.get(constants.PROP_TECHNIQUE) != constants.TECHNIQUE_CODE_CONFIG_PARSER - ] - - codemeta_output["softwareRequirements"] = ( - code_parser_requirements if code_parser_requirements else other_requirements - ) if constants.CAT_CONTINUOUS_INTEGRATION in repo_data: - codemeta_output["continuousIntegration"] = repo_data[constants.CAT_CONTINUOUS_INTEGRATION][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_CONTINUOUSINTEGRATION] = repo_data[constants.CAT_CONTINUOUS_INTEGRATION][0][constants.PROP_RESULT][constants.PROP_VALUE] # if constants.CAT_WORKFLOWS in repo_data: # codemeta_output["workflows"] = repo_data[constants.CAT_WORKFLOWS][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_RELEASES in repo_data: @@ -212,11 +265,11 @@ def format_date(date_string): oldest_version = l[constants.PROP_RESULT].get(constants.PROP_TAG) if latest_description is not None: - codemeta_output["releaseNotes"] = latest_description + codemeta_output[constants.CAT_CODEMETA_RELEASENOTES] = latest_description if latest_version is not None: - codemeta_output["softwareVersion"] = latest_version + codemeta_output[constants.CAT_CODEMETA_SOFTWAREVERSION] = latest_version if oldest_date is not None: - codemeta_output["datePublished"] = format_date(oldest_date.isoformat()) + codemeta_output[constants.CAT_CODEMETA_DATEPUBLISHED] = format_date(oldest_date.isoformat()) install_links = [] if constants.CAT_INSTALLATION in repo_data: @@ -237,22 +290,76 @@ def format_date(date_string): if len(install_links) > 0: # remove duplicates and generate codemeta install_links = list(set(install_links)) - codemeta_output["buildInstructions"] = install_links + codemeta_output[constants.CAT_CODEMETA_BUILDINSTRUCTIONS] = install_links if constants.CAT_OWNER in repo_data: # if user then person, otherwise organization type_aux = repo_data[constants.CAT_OWNER][0][constants.PROP_RESULT][constants.PROP_TYPE] if type_aux == "User": type_aux = "Person" - codemeta_output["author"] = [ + codemeta_output[constants.CAT_CODEMETA_AUTHOR] = [ { "@type": type_aux, "@id": "https://github.com/" + author_name } ] + if constants.CAT_AUTHORS in repo_data: + if "author" not in codemeta_output: + codemeta_output[constants.CAT_CODEMETA_AUTHOR] = [] + + # print('-------AUTHORES') + # print(repo_data[constants.CAT_AUTHORS]) + for author in repo_data[constants.CAT_AUTHORS]: + value_author = author[constants.PROP_RESULT].get(constants.PROP_VALUE) + name_author = author[constants.PROP_RESULT].get(constants.PROP_NAME) + if value_author and re.search(constants.REGEXP_LTD_INC, value_author, re.IGNORECASE): + type_author = "Organization" + else: + type_author = "Person" + + author_l = { + "@type": type_author + } + + if type_author == "Organization": + if name_author: + author_l['name'] = name_author + else: + family_name = None + given_name = None + + if author[constants.PROP_RESULT].get('last_name'): + family_name = author[constants.PROP_RESULT].get('last_name') + author_l['familyName'] = family_name + if author[constants.PROP_RESULT].get('given_name'): + given_name = author[constants.PROP_RESULT].get('given_name') + author_l['givenName'] = given_name + if author[constants.PROP_RESULT].get('email'): + mail_author = author[constants.PROP_RESULT].get('email') + author_l['email'] = mail_author + + if name_author: + author_l['name'] = name_author + else: + author_l['name'] = value_author + + existing_authors = codemeta_output.get(constants.CAT_CODEMETA_AUTHOR, []) + existing = next((a for a in existing_authors if a.get("name") == author_l["name"]), None) + + if existing: + for key, val in author_l.items(): + if key not in existing or not existing[key]: + existing[key] = val + else: + codemeta_output[constants.CAT_CODEMETA_AUTHOR].append(author_l) + # if not any(a.get('name') == author_l['name'] for a in existing_authors): + # codemeta_output[constants.CAT_CODEMETA_AUTHOR].append(author_l) + + if constants.CAT_CITATION in repo_data: # url_cit = [] - codemeta_output["referencePublication"] = [] - scholarlyArticles = {} + codemeta_output[constants.CAT_CODEMETA_REFERENCEPUBLICATION] = [] + all_reference_publications = [] + # scholarlyArticles = {} author_orcids = {} for cit in repo_data[constants.CAT_CITATION]: @@ -268,7 +375,6 @@ def format_date(date_string): doi = yaml_content.get("doi") or preferred_citation.get("doi") identifiers = yaml_content.get("identifiers", []) url_citation = preferred_citation.get("url") or yaml_content.get("url") - identifier_url = next((id["value"] for id in identifiers if id["type"] == "url"), None) identifier_doi = next((id["value"] for id in identifiers if id["type"] == "doi"), None) @@ -329,14 +435,9 @@ def format_date(date_string): if constants.PROP_DOI in cit[constants.PROP_RESULT].keys(): doi = cit[constants.PROP_RESULT][constants.PROP_DOI] scholarlyArticle[constants.CAT_IDENTIFIER] = cit[constants.PROP_RESULT][constants.PROP_DOI] - # elif constants.PROP_FORMAT in cit[constants.PROP_RESULT].keys() \ - # and cit[constants.PROP_RESULT][constants.PROP_FORMAT] == constants.FORMAT_CFF: - # url_cit.append(cit[constants.PROP_SOURCE]) if constants.PROP_URL in cit[constants.PROP_RESULT].keys(): scholarlyArticle[constants.PROP_URL] = cit[constants.PROP_RESULT][constants.PROP_URL] - # if constants.PROP_AUTHOR in cit[constants.PROP_RESULT].keys(): - # scholarlyArticle[constants.PROP_AUTHOR] = cit[constants.PROP_RESULT][constants.PROP_AUTHOR] if constants.PROP_TITLE in cit[constants.PROP_RESULT].keys(): title = normalize_title(cit[constants.PROP_RESULT][constants.PROP_TITLE]) @@ -356,18 +457,12 @@ def format_date(date_string): else: scholarlyArticle = extract_scholarly_article_natural(cit[constants.PROP_RESULT][constants.PROP_VALUE], scholarlyArticle, 'CODEMETA') - key = (doi, title) + all_reference_publications.append({ + **scholarlyArticle, + "_source_format": "cff" if not is_bibtex else "bibtex" + }) - if key in scholarlyArticles: - if is_bibtex: - codemeta_output["referencePublication"].remove(scholarlyArticles[key]) - codemeta_output["referencePublication"].append(scholarlyArticle) - scholarlyArticles[key] = scholarlyArticle - else: - codemeta_output["referencePublication"].append(scholarlyArticle) - scholarlyArticles[key] = scholarlyArticle - - for article in codemeta_output["referencePublication"]: + for article in all_reference_publications: if "author" in article: for author in article["author"]: family_name = author.get("familyName", "").strip() @@ -376,21 +471,67 @@ def format_date(date_string): if key and key in author_orcids: author["@id"] = author_orcids[key] + + codemeta_output[constants.CAT_CODEMETA_REFERENCEPUBLICATION] = deduplicate_publications(all_reference_publications) if constants.CAT_STATUS in repo_data: url_status = repo_data[constants.CAT_STATUS][0]['result'].get('value', '') status = url_status.split('#')[-1] if '#' in url_status else None if status: - codemeta_output["developmentStatus"] = status + codemeta_output[constants.CAT_CODEMETA_DEVELOPMENTSTATUS] = status + if constants.CAT_IDENTIFIER in repo_data: - codemeta_output["identifier"] = repo_data[constants.CAT_IDENTIFIER][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_IDENTIFIER] = [] + + for identifier in repo_data[constants.CAT_IDENTIFIER]: + value = identifier[constants.PROP_RESULT][constants.PROP_VALUE] + if value not in codemeta_output[constants.CAT_CODEMETA_IDENTIFIER]: + codemeta_output[constants.CAT_CODEMETA_IDENTIFIER].append(value) + + if constants.CAT_HOMEPAGE in repo_data: + + # example + # homepage_urls = {"http://foo.com", "https://foo.com", "http://bar.com"} + # Result--> filtered_urls = {"https://foo.com", "http://bar.com"} + # Prioritize https + + homepage_urls = {hp[constants.PROP_RESULT][constants.PROP_VALUE].strip() + for hp in repo_data[constants.CAT_HOMEPAGE]} + + filtered_urls = set() + roots_with_https = {url[len("https://"):] for url in homepage_urls if url.startswith("https://")} + + for url in homepage_urls: + root = url.replace("http://", "").replace("https://", "") + if url.startswith("http://") and root in roots_with_https: + continue + filtered_urls.add(url) + + codemeta_output[constants.CAT_CODEMETA_URL] = list(filtered_urls) + + # codemeta_output["identifier"] = repo_data[constants.CAT_IDENTIFIER][0][constants.PROP_RESULT][constants.PROP_VALUE] if constants.CAT_README_URL in repo_data: - codemeta_output["readme"] = repo_data[constants.CAT_README_URL][0][constants.PROP_RESULT][constants.PROP_VALUE] + codemeta_output[constants.CAT_CODEMETA_README] = repo_data[constants.CAT_README_URL][0][constants.PROP_RESULT][constants.PROP_VALUE] + + if constants.CAT_RUNTIME_PLATFORM in repo_data: + runtimes = [] + + for runtime_entry in repo_data[constants.CAT_RUNTIME_PLATFORM]: + result = runtime_entry.get("result", {}) + # name = result.get("name") + value = result.get("value") + if value: + # runtimes.append(f"{name} {version}") + runtimes.append(value) + + if runtimes: + codemeta_output[constants.CAT_CODEMETA_RUNTIMEPLATFORM] = ", ".join(runtimes) + # if "contributors" in repo_data: # codemeta_output["contributor"] = data_path(["contributors", "excerpt"]) # A person is expected, and we extract text at the moment if descriptions_text: - codemeta_output["description"] = descriptions_text + codemeta_output[constants.CAT_CODEMETA_DESCRIPTION] = descriptions_text # if published_date != "": # commenting this out because we cannot assume the last published date to be the published date # codemeta_output["datePublished"] = published_date @@ -408,10 +549,70 @@ def create_missing_fields(result): The categories are added to the JSON results. This won't be added if you export TTL or Codemeta""" missing = [] repo_data = result - for c in constants.categories_files_header: + # for c in constants.categories_files_header: + for c in constants.all_categories: if c not in repo_data: missing.append(c) return missing -def normalize_title(title): - return re.sub(r"\s+", " ", title.strip().lower()) if title else None +# def normalize_title(title): +# return re.sub(r"\s+", " ", title.strip().lower()) if title else None + +def normalize_title(title: str) -> str: + if not title: + return None + title = re.sub(r'[{}]', '', title) + title = re.sub(r'\s+', ' ', title) + return title.strip().lower() + + +def deduplicate_publications(publications: List[Dict]) -> List[Dict]: + seen = {} + for pub in publications: + # doi = pub.get("identifier", "").lower().strip() + # doi = (pub.get("identifier") or "").lower().strip() + doi = extract_doi(pub.get("identifier") or "") + title = normalize_title(pub.get("name", "")) + key = (doi, title) + + if key not in seen: + seen[key] = pub + else: + existing = seen[key] + existing_format = existing.get("_source_format", "") + new_format = pub.get("_source_format", "") + existing_url = (existing.get("url") or "").lower() + new_url = (pub.get("url") or "").lower() + + # is_doi_url_existing = existing_url.startswith("https://doi.org/") + # is_doi_url_new = new_url.startswith("https://doi.org/") + doi_existing = extract_doi(existing_url) + # print(f'-----> DOI existing: {doi_existing}') + doi_new = extract_doi(new_url) + # print(f'-----> DOI existing: {doi_new}') + is_doi_url_existing = bool(doi_existing) + is_doi_url_new = bool(doi_new) + + # Priority CFF + if existing_format != "cff" and new_format == "cff": + seen[key] = pub + + # Priority DOI URL + elif existing_format == new_format: + if not is_doi_url_existing and is_doi_url_new: + seen[key] = pub + + result = [] + for pub in seen.values(): + pub.pop("_source_format", None) + result.append(pub) + + return result + + +def extract_doi(url: str) -> str: + if not url: + return "" + + match = re.search(constants.REGEXP_ALL_DOIS, url, re.IGNORECASE) + return match.group(0).lower() if match else "" diff --git a/src/somef_core/extract_software_type 2.py b/src/somef_core/extract_software_type 2.py new file mode 100644 index 0000000..27aebea --- /dev/null +++ b/src/somef_core/extract_software_type 2.py @@ -0,0 +1,329 @@ +import os +from pathlib import Path +import nbformat +from nbformat.reader import NotJSONError +from chardet import detect +import re +from .extract_workflows import is_file_workflow +from .process_results import Result +from .utils import constants +# from .extract_ontologies import is_file_ontology + +import pdb + + +def check_repository_type(path_repo, title, metadata_result: Result): + """ Function that adds the metadata result in the JSON + output depending on the software type or if the repository is not considered software""" + + if check_static_websites(path_repo, metadata_result): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'static-website', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + # elif check_ontologies(path_repo): + # metadata_result.add_result(constants.CAT_TYPE, + # { + # constants.PROP_VALUE: 'ontology', + # constants.PROP_TYPE: constants.STRING + # }, + # 1, + # constants.TECHNIQUE_HEURISTICS) + elif check_notebooks(path_repo): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'notebook-application', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + # commenting out this heuristic, as if a repository contains other files apart from workflows, it may not be a wf + # elif check_workflow(path_repo, title): + # metadata_result.add_result(constants.CAT_TYPE, + # { + # constants.PROP_VALUE: 'workflow', + # constants.PROP_TYPE: constants.STRING + # }, + # 1, + # constants.TECHNIQUE_HEURISTICS) + elif check_command_line(path_repo): + """The 0.82 confidence result is from running the analysis on 300 repos and showing the precision + of the heuristic""" + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'commandline-application', + constants.PROP_TYPE: constants.STRING + }, + 0.82, + constants.TECHNIQUE_HEURISTICS) + + elif check_extras(path_repo): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'non-software', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + return metadata_result + + +def check_notebooks(path_repo): + """Function which checks if the specified repository is a Notebook Application + depending on the extensions present and number of notebooks which contain code + + The function checks for presence of more than one code_notebook inside the repo and checks against code + extensions present returning true if both conditions are fulfilled .""" + code_notebooks = 0 + total_files = 0 + + bad_extensions = False + for root, dirs, files in os.walk(path_repo): + for file in files: + if file.endswith((".ipynb", ".rmd", '.Rmd')): + notebook_path = os.path.join(root, file) + try: + if file.endswith(".ipynb"): + if is_notebook_code(notebook_path): + code_notebooks += 1 + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(notebook_path): + code_notebooks += 1 + except Exception as e: + print(f"Error reading notebook file {notebook_path}: {str(e)}") + pass + if file.endswith(constants.code_extensions): + bad_extensions = True + if code_notebooks > 1: + return not bad_extensions + return False + + +# def check_ontologies(path_repo): +# """Function which detects if repository is an Ontology based on files present +# and the non-existence of code files""" +# ontology = False +# for root, dirs, files in os.walk(path_repo): +# repo_relative_path = os.path.relpath(root, path_repo) +# for file in files: +# file_path = os.path.join(repo_relative_path, file) +# # print(os.path.join(repo_relative_path,file_path)) +# if file.endswith(constants.code_extensions): +# return False +# elif file.endswith(constants.ontology_extensions): +# if not ontology: +# ontology = is_file_ontology(os.path.join(path_repo, file_path)) +# return ontology + + +def check_command_line(path_repo): + """Function which detects if repository is a Commandline Application + based on README analysis of commandline arguments and implementations""" + pattern_commandline = r"(?i)command[-\s]?line" + pattern_cmd_arg = r"(?i)(explanation\s+of\s+)?arguments\b" + pattern_cmd_arg2 = r"(?i)-\w+:" + for dir_path, dir_names, filenames in os.walk(path_repo): + repo_relative_path = os.path.relpath(dir_path, path_repo) + for filename in filenames: + file_path = os.path.join(repo_relative_path, filename) + filename_no_ext = os.path.splitext(filename)[0] + if "README" == filename_no_ext.upper(): + if repo_relative_path == ".": + try: + # print(os.path.join(dir_path, filename)) + with open(os.path.join(dir_path, filename), "r", encoding="utf-8") as data_file: + data_file_text = data_file.read() + try: + cmd_match2 = re.search(pattern_commandline, data_file_text) + cmd_match3 = re.search(pattern_cmd_arg, data_file_text) + cmd_match4 = re.search(pattern_cmd_arg2, data_file_text) + if cmd_match2 or (cmd_match3 and cmd_match4): + return True + except: + return False + except: + pass + + return False + + +def check_extras(path_repo): + """Function which detects if a repository is non-software by checking against + software related files""" + for root, dirs, files in os.walk(path_repo): + for file in files: + notebook_path = os.path.join(root, file) + if file.endswith(constants.code_extensions) or file.endswith(constants.ontology_extensions): + return False + elif file.endswith(".ipynb"): + if is_notebook_code(notebook_path): + return False + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(notebook_path): + return False + return True + + +def check_static_websites(path_repo, repo_metadata: Result): + """Function that analyzes byte size of js,css,html languages and checks if + repository contains files not associated with static websites + + The evaluation numbers were extracted from the analysis of 997 css repositories representing libraries nad 998 js repos containing libraries + with control repositories . + + """ + # print(path_repo) + nr_files = 0 + web_files = 0 + total_size = 0 + js_size = 0 + css_size = 0 + html_file = 0 + for root, dirs, files in os.walk(path_repo): + for file in files: + file_path = os.path.join(root, file) + if file.endswith(constants.code_extensions) or file.endswith( + constants.ontology_extensions) or file.lower() in (('bower.json', 'package.json')): + return False + elif file.endswith((".js", ".css", ".scss")): + web_files += 1 + elif file.endswith(".html"): + html_file += 1 + elif file.endswith(".ipynb"): + if is_notebook_code(file_path): + return False + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(file_path): + return False + try: + languages = repo_metadata[constants.CAT_PROGRAMMING_LANGUAGES] + print(languages) + for language in languages: + language_name = language[constants.PROP_RESULT][constants.PROP_NAME] + print(language_name) + if language_name.lower() == "javascript": + js_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + print(js_size) + elif language_name.lower() == "scss" or language_name.lower() == "css": + css_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + total_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + except Exception as e: + print(e) + if html_file > 0: + if js_size > 0 and css_size == 0: + if js_size / total_size < 0.91: + return True + elif js_size == 0 and css_size > 0: + if css_size / total_size < 0.798: + return True + return True + + return False + + +def check_workflow(repo_path, title): + """Function which checks inside text for presence of repository being a workflow and analysis of the + files inside to check if they are correct workflow files. Also checks for repositories with no information + the name of the files which might point to it being a workflow. + PARAMETERS: + @repo_path(path to the repository directory) + @title(title of the repository) + """ + list = [] + total_workflows = 0 + good_workflows = 0 + for root, dirs, files in os.walk(repo_path): + repo_relative_path = os.path.relpath(root, repo_path) + for file in files: + filename_no_ext = os.path.splitext(file)[0] + if "README" == filename_no_ext.upper(): + if repo_relative_path == ".": + try: + with open(os.path.join(root, file), "r") as readme_file: + readme_contents = readme_file.read() + + title_words = title.split() + + pattern = r'([^.?!]*(?:\b|\W){}(?:\b|\W)[^.?!]*[.?!])'.format( + '|'.join(map(re.escape, title_words))) + sentences = re.findall(pattern, readme_contents, flags=re.IGNORECASE) + for sentence in sentences: + if re.search(rf'\b{title}\b', sentence, flags=re.IGNORECASE) and re.search( + r'\b(pipeline|workflow)\b', sentence, flags=re.IGNORECASE): + return True + + pattern_md = r'##.*\b(workflow|pipeline)\b' + pattern_rst = r'^([^=\n]+(?:\n(?![-=]).*)*\b(workflow|pipeline)\b(?:\n(?![-=]).*)*)\n=+' + + match_md = re.findall(pattern_md, readme_contents, re.IGNORECASE) + match_rst = re.findall(pattern_rst, readme_contents, re.MULTILINE | re.IGNORECASE) + + if match_md or match_rst: + return True + + except: + continue + + if file.endswith(constants.workflow_extensions) or file == "Snakefile": + total_workflows += 1 + file_path = os.path.join(root, file) + if is_file_workflow(file_path): + list.append(file_path) + good_workflows += 1 + else: + continue + if check_name(file): + return True + if list != []: + return True + else: + return False + + +def check_name(filename): + """Assisting function for check_workflow to look for specific named files""" + pattern1 = re.compile(r"pipeline", re.IGNORECASE) + pattern2 = re.compile(r"(model|example)", re.IGNORECASE) + programming_language_extensions = ( + ".py", ".java", ".cpp", ".c", ".php", ".rb", ".js", ".html", ".css", ".go", ".swift", ".scala", ".pl", ".ipynb") + if pattern1.search(filename) and pattern2.search(filename): + if filename.endswith(programming_language_extensions): + return True + elif pattern1.search(filename) and not pattern2.search(filename): + return False + elif (not pattern1.search(filename) and not pattern2.search(filename)) or ( + not pattern1.search(filename) and pattern2.search(filename)): + return False + + +def is_notebook_code(file_path): + has_code = False + num_code_cells = 0 + num_total_cells = 0 + try: + nb = nbformat.read(file_path, as_version=4) + + for cell in nb['cells']: + if cell['cell_type'] == 'code': + num_total_cells += 1 + if cell['source'].strip(): + num_code_cells += 1 + has_code = True + return has_code + except NotJSONError: + return False + except Exception: + return False + + +def has_code_in_rmd(file_path): + try: + with open(file_path, 'r') as file: + content = file.read() + if "```{r" in content or "```{python" in content or "```{bash" in content: + return True + except: + return False diff --git a/src/somef_core/extract_software_type.py b/src/somef_core/extract_software_type.py new file mode 100644 index 0000000..27aebea --- /dev/null +++ b/src/somef_core/extract_software_type.py @@ -0,0 +1,329 @@ +import os +from pathlib import Path +import nbformat +from nbformat.reader import NotJSONError +from chardet import detect +import re +from .extract_workflows import is_file_workflow +from .process_results import Result +from .utils import constants +# from .extract_ontologies import is_file_ontology + +import pdb + + +def check_repository_type(path_repo, title, metadata_result: Result): + """ Function that adds the metadata result in the JSON + output depending on the software type or if the repository is not considered software""" + + if check_static_websites(path_repo, metadata_result): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'static-website', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + # elif check_ontologies(path_repo): + # metadata_result.add_result(constants.CAT_TYPE, + # { + # constants.PROP_VALUE: 'ontology', + # constants.PROP_TYPE: constants.STRING + # }, + # 1, + # constants.TECHNIQUE_HEURISTICS) + elif check_notebooks(path_repo): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'notebook-application', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + # commenting out this heuristic, as if a repository contains other files apart from workflows, it may not be a wf + # elif check_workflow(path_repo, title): + # metadata_result.add_result(constants.CAT_TYPE, + # { + # constants.PROP_VALUE: 'workflow', + # constants.PROP_TYPE: constants.STRING + # }, + # 1, + # constants.TECHNIQUE_HEURISTICS) + elif check_command_line(path_repo): + """The 0.82 confidence result is from running the analysis on 300 repos and showing the precision + of the heuristic""" + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'commandline-application', + constants.PROP_TYPE: constants.STRING + }, + 0.82, + constants.TECHNIQUE_HEURISTICS) + + elif check_extras(path_repo): + metadata_result.add_result(constants.CAT_TYPE, + { + constants.PROP_VALUE: 'non-software', + constants.PROP_TYPE: constants.STRING + }, + 1, + constants.TECHNIQUE_HEURISTICS) + return metadata_result + + +def check_notebooks(path_repo): + """Function which checks if the specified repository is a Notebook Application + depending on the extensions present and number of notebooks which contain code + + The function checks for presence of more than one code_notebook inside the repo and checks against code + extensions present returning true if both conditions are fulfilled .""" + code_notebooks = 0 + total_files = 0 + + bad_extensions = False + for root, dirs, files in os.walk(path_repo): + for file in files: + if file.endswith((".ipynb", ".rmd", '.Rmd')): + notebook_path = os.path.join(root, file) + try: + if file.endswith(".ipynb"): + if is_notebook_code(notebook_path): + code_notebooks += 1 + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(notebook_path): + code_notebooks += 1 + except Exception as e: + print(f"Error reading notebook file {notebook_path}: {str(e)}") + pass + if file.endswith(constants.code_extensions): + bad_extensions = True + if code_notebooks > 1: + return not bad_extensions + return False + + +# def check_ontologies(path_repo): +# """Function which detects if repository is an Ontology based on files present +# and the non-existence of code files""" +# ontology = False +# for root, dirs, files in os.walk(path_repo): +# repo_relative_path = os.path.relpath(root, path_repo) +# for file in files: +# file_path = os.path.join(repo_relative_path, file) +# # print(os.path.join(repo_relative_path,file_path)) +# if file.endswith(constants.code_extensions): +# return False +# elif file.endswith(constants.ontology_extensions): +# if not ontology: +# ontology = is_file_ontology(os.path.join(path_repo, file_path)) +# return ontology + + +def check_command_line(path_repo): + """Function which detects if repository is a Commandline Application + based on README analysis of commandline arguments and implementations""" + pattern_commandline = r"(?i)command[-\s]?line" + pattern_cmd_arg = r"(?i)(explanation\s+of\s+)?arguments\b" + pattern_cmd_arg2 = r"(?i)-\w+:" + for dir_path, dir_names, filenames in os.walk(path_repo): + repo_relative_path = os.path.relpath(dir_path, path_repo) + for filename in filenames: + file_path = os.path.join(repo_relative_path, filename) + filename_no_ext = os.path.splitext(filename)[0] + if "README" == filename_no_ext.upper(): + if repo_relative_path == ".": + try: + # print(os.path.join(dir_path, filename)) + with open(os.path.join(dir_path, filename), "r", encoding="utf-8") as data_file: + data_file_text = data_file.read() + try: + cmd_match2 = re.search(pattern_commandline, data_file_text) + cmd_match3 = re.search(pattern_cmd_arg, data_file_text) + cmd_match4 = re.search(pattern_cmd_arg2, data_file_text) + if cmd_match2 or (cmd_match3 and cmd_match4): + return True + except: + return False + except: + pass + + return False + + +def check_extras(path_repo): + """Function which detects if a repository is non-software by checking against + software related files""" + for root, dirs, files in os.walk(path_repo): + for file in files: + notebook_path = os.path.join(root, file) + if file.endswith(constants.code_extensions) or file.endswith(constants.ontology_extensions): + return False + elif file.endswith(".ipynb"): + if is_notebook_code(notebook_path): + return False + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(notebook_path): + return False + return True + + +def check_static_websites(path_repo, repo_metadata: Result): + """Function that analyzes byte size of js,css,html languages and checks if + repository contains files not associated with static websites + + The evaluation numbers were extracted from the analysis of 997 css repositories representing libraries nad 998 js repos containing libraries + with control repositories . + + """ + # print(path_repo) + nr_files = 0 + web_files = 0 + total_size = 0 + js_size = 0 + css_size = 0 + html_file = 0 + for root, dirs, files in os.walk(path_repo): + for file in files: + file_path = os.path.join(root, file) + if file.endswith(constants.code_extensions) or file.endswith( + constants.ontology_extensions) or file.lower() in (('bower.json', 'package.json')): + return False + elif file.endswith((".js", ".css", ".scss")): + web_files += 1 + elif file.endswith(".html"): + html_file += 1 + elif file.endswith(".ipynb"): + if is_notebook_code(file_path): + return False + elif file.endswith(".rmd") or file.endswith('.Rmd'): + if has_code_in_rmd(file_path): + return False + try: + languages = repo_metadata[constants.CAT_PROGRAMMING_LANGUAGES] + print(languages) + for language in languages: + language_name = language[constants.PROP_RESULT][constants.PROP_NAME] + print(language_name) + if language_name.lower() == "javascript": + js_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + print(js_size) + elif language_name.lower() == "scss" or language_name.lower() == "css": + css_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + total_size += language[constants.PROP_RESULT][constants.PROP_SIZE] + except Exception as e: + print(e) + if html_file > 0: + if js_size > 0 and css_size == 0: + if js_size / total_size < 0.91: + return True + elif js_size == 0 and css_size > 0: + if css_size / total_size < 0.798: + return True + return True + + return False + + +def check_workflow(repo_path, title): + """Function which checks inside text for presence of repository being a workflow and analysis of the + files inside to check if they are correct workflow files. Also checks for repositories with no information + the name of the files which might point to it being a workflow. + PARAMETERS: + @repo_path(path to the repository directory) + @title(title of the repository) + """ + list = [] + total_workflows = 0 + good_workflows = 0 + for root, dirs, files in os.walk(repo_path): + repo_relative_path = os.path.relpath(root, repo_path) + for file in files: + filename_no_ext = os.path.splitext(file)[0] + if "README" == filename_no_ext.upper(): + if repo_relative_path == ".": + try: + with open(os.path.join(root, file), "r") as readme_file: + readme_contents = readme_file.read() + + title_words = title.split() + + pattern = r'([^.?!]*(?:\b|\W){}(?:\b|\W)[^.?!]*[.?!])'.format( + '|'.join(map(re.escape, title_words))) + sentences = re.findall(pattern, readme_contents, flags=re.IGNORECASE) + for sentence in sentences: + if re.search(rf'\b{title}\b', sentence, flags=re.IGNORECASE) and re.search( + r'\b(pipeline|workflow)\b', sentence, flags=re.IGNORECASE): + return True + + pattern_md = r'##.*\b(workflow|pipeline)\b' + pattern_rst = r'^([^=\n]+(?:\n(?![-=]).*)*\b(workflow|pipeline)\b(?:\n(?![-=]).*)*)\n=+' + + match_md = re.findall(pattern_md, readme_contents, re.IGNORECASE) + match_rst = re.findall(pattern_rst, readme_contents, re.MULTILINE | re.IGNORECASE) + + if match_md or match_rst: + return True + + except: + continue + + if file.endswith(constants.workflow_extensions) or file == "Snakefile": + total_workflows += 1 + file_path = os.path.join(root, file) + if is_file_workflow(file_path): + list.append(file_path) + good_workflows += 1 + else: + continue + if check_name(file): + return True + if list != []: + return True + else: + return False + + +def check_name(filename): + """Assisting function for check_workflow to look for specific named files""" + pattern1 = re.compile(r"pipeline", re.IGNORECASE) + pattern2 = re.compile(r"(model|example)", re.IGNORECASE) + programming_language_extensions = ( + ".py", ".java", ".cpp", ".c", ".php", ".rb", ".js", ".html", ".css", ".go", ".swift", ".scala", ".pl", ".ipynb") + if pattern1.search(filename) and pattern2.search(filename): + if filename.endswith(programming_language_extensions): + return True + elif pattern1.search(filename) and not pattern2.search(filename): + return False + elif (not pattern1.search(filename) and not pattern2.search(filename)) or ( + not pattern1.search(filename) and pattern2.search(filename)): + return False + + +def is_notebook_code(file_path): + has_code = False + num_code_cells = 0 + num_total_cells = 0 + try: + nb = nbformat.read(file_path, as_version=4) + + for cell in nb['cells']: + if cell['cell_type'] == 'code': + num_total_cells += 1 + if cell['source'].strip(): + num_code_cells += 1 + has_code = True + return has_code + except NotJSONError: + return False + except Exception: + return False + + +def has_code_in_rmd(file_path): + try: + with open(file_path, 'r') as file: + content = file.read() + if "```{r" in content or "```{python" in content or "```{bash" in content: + return True + except: + return False diff --git a/src/somef_core/extract_workflows.py b/src/somef_core/extract_workflows.py index a1426e9..f07037d 100644 --- a/src/somef_core/extract_workflows.py +++ b/src/somef_core/extract_workflows.py @@ -1,4 +1,5 @@ import re +import logging Galaxy_pattern = r"(?i)a[_\s-]?galaxy[_\s-]?workflow" CWL_pattern = r"\bclass:\s*[Ww]orkflow\b" @@ -9,6 +10,32 @@ GitLab_ContinuosIntegration_keywords = [r"script:", r"rules:", r"variables:", r"before_script:", r"after_script:", r"image:"] +def is_file_workflow(file_path): + try: + with open(file_path, "rb") as file: + raw_data = file.read() + + try: + content = raw_data.decode("utf-8") + except UnicodeDecodeError: + logging.warning(f"File {file_path} is not UTF-8 decodable. Skipping.") + return False + + Galaxy_match = re.search(Galaxy_pattern, content) + CWL_match = re.search(CWL_pattern, content) + Workflow_match = re.search(Workflow_content_pattern, content) + Workflow_match_2 = re.search(workflow_pattern, content, re.IGNORECASE) + Nextflow_match = re.search(Nextflow_pattern, content) + + if Galaxy_match or CWL_match or Workflow_match or Workflow_match_2 or Nextflow_match: + return True + else: + return False + + except Exception as e: + logging.warning(f"Error reading file {file_path}: {e}") + return False + def is_file_continuous_integration_gitlab(file_path): """Detects if a file is a GitLab CI/CD pipeline.""" with open(file_path, 'r') as file: diff --git a/src/somef_core/header_analysis.py b/src/somef_core/header_analysis.py index 1545fdb..4a4088d 100644 --- a/src/somef_core/header_analysis.py +++ b/src/somef_core/header_analysis.py @@ -9,9 +9,14 @@ from .process_results import Result from .parser import mardown_parser from .utils import constants - +from typing import Dict, Iterable, List, Tuple +from functools import lru_cache pd.options.mode.chained_assignment = None # default='warn' + +SIMILARITY_THRESHOLD = 0.8 + + # Define wordnet groups group = dict() @@ -81,36 +86,69 @@ Word("report").synsets[6]] group.update({constants.CAT_SUPPORT: support}) - -def extract_bash_code(text): - """Function to detect code blocks""" - split = text.split("```") - output = [] - if len(split) >= 3: - for index, value in enumerate(split): - if index % 2 == 1: - output.append(split[index]) - return output - - -def extract_header_content(text): - """Function designed to extract headers and contents of text and place it in a dataframe""" - header = [] +@lru_cache(maxsize=4096) +def get_synsets(word: str): + """Cached access to WordNet synsets.""" + return Word(word).synsets + + +@lru_cache(maxsize=16384) +def path_similarity_cached(sense1, sense2) -> float: + """Cached path similarity lookup.""" + sim = sense1.path_similarity(sense2) + return sim if sim is not None else 0.0 + +# def extract_bash_code(text): +# """Function to detect code blocks""" +# split = text.split("```") +# output = [] +# if len(split) >= 3: +# for index, value in enumerate(split): +# if index % 2 == 1: +# output.append(split[index]) +# return output +def extract_bash_code(text: str) -> List[str]: + blocks = text.split("```") + return [blocks[i] for i in range(1, len(blocks), 2)] + +# def extract_header_content(text): +# """Function designed to extract headers and contents of text and place it in a dataframe""" +# header = [] +# headers = mardown_parser.extract_headers(text) +# for key in headers.keys(): +# if headers[key]: +# header.append(key) +# content, none_header_content = mardown_parser.extract_content_per_header(text, headers) +# parent_headers = mardown_parser.extract_headers_parents(text) +# # into dataframe +# df = pd.DataFrame(columns=['Header', 'Content', 'ParentHeader']) +# dfs = [pd.DataFrame({'Header': [i], 'Content': [j], 'ParentHeader': [parent_headers.get(i, None)]}) for i, j in +# zip(header, content)] +# df = pd.concat(dfs, ignore_index=True) +# # for i, j in zip(header, content): +# # df = df.append({'Header': i, 'Content': j, 'ParentHeader': parent_headers[i]}, ignore_index=True) +# # df['Content'].replace('', np.nan, inplace=True) +# df['Content'] = df['Content'].replace('', np.nan) + +# df.dropna(subset=['Content'], inplace=True) +# return df, none_header_content +def extract_header_content(text: str) -> Tuple[pd.DataFrame, str | None]: headers = mardown_parser.extract_headers(text) - for key in headers.keys(): - if headers[key]: - header.append(key) + header_list = [h for h, v in headers.items() if v] + content, none_header_content = mardown_parser.extract_content_per_header(text, headers) - parent_headers = mardown_parser.extract_headers_parents(text) - # into dataframe - df = pd.DataFrame(columns=['Header', 'Content', 'ParentHeader']) - dfs = [pd.DataFrame({'Header': [i], 'Content': [j], 'ParentHeader': [parent_headers.get(i, None)]}) for i, j in - zip(header, content)] - df = pd.concat(dfs, ignore_index=True) - # for i, j in zip(header, content): - # df = df.append({'Header': i, 'Content': j, 'ParentHeader': parent_headers[i]}, ignore_index=True) - df['Content'].replace('', np.nan, inplace=True) + parents = mardown_parser.extract_headers_parents(text) + + df = pd.DataFrame({ + 'Header': header_list, + 'Content': content, + 'ParentHeader': [parents.get(h) for h in header_list], + }) + + # df['Content'].replace('', np.nan, inplace=True) + df['Content'] = df['Content'].replace('', np.nan) df.dropna(subset=['Content'], inplace=True) + return df, none_header_content @@ -136,21 +174,21 @@ def find_sim(wordlist, wd): return 0 -def match_group(word_syn, group, threshold): - """Function designed to match a word with a subgroup""" - currmax = 0 - maxgroup = "" - simvalues = dict() - for sense in word_syn: # for a given sense of a word - similarities = [] - for key, value in group.items(): # value has all the similar words - path_sim = find_sim(value, sense) - # print("Similarity is:",path_sim) - if path_sim > threshold: # then append to the list - if path_sim > currmax: - maxgroup = key - currmax = path_sim - return maxgroup +# def match_group(word_syn, group, threshold): +# """Function designed to match a word with a subgroup""" +# currmax = 0 +# maxgroup = "" +# simvalues = dict() +# for sense in word_syn: # for a given sense of a word +# similarities = [] +# for key, value in group.items(): # value has all the similar words +# path_sim = find_sim(value, sense) +# # print("Similarity is:",path_sim) +# if path_sim > threshold: # then append to the list +# if path_sim > currmax: +# maxgroup = key +# currmax = path_sim +# return maxgroup def label_header(header): @@ -160,11 +198,12 @@ def label_header(header): sentence = header_clean.strip().split(" ") label = [] for s in sentence: - synn = Word(s).synsets + synn = Word(s).synsets if len(synn) > 0: - bestgroup = match_group(synn, group, 0.8) + # bestgroup = match_group(synn, group, 0.8) + bestgroup = match_group(synn) if bestgroup != "" and bestgroup not in label: - label.append(bestgroup) + label.append(bestgroup) return label @@ -180,7 +219,8 @@ def label_parent_headers(parentHeaders): for s in sentence: synn = Word(s).synsets if len(synn) > 0: - bestgroup = match_group(synn, group, 0.8) + # bestgroup = match_group(synn, group, 0.8) + bestgroup = match_group(synn) if bestgroup != "" and bestgroup not in label: label.append(bestgroup) return label @@ -193,75 +233,285 @@ def clean_html(text): return cleantext -def extract_categories(repo_data, repository_metadata: Result): - """ - Function that adds category information extracted using header information - Parameters - ---------- - @param repo_data: data to use the header analysis - @param repository_metadata: Result object with the results found so far in the repo - - Returns - ------- - @return Result with the information added. - """ +def max_similarity(word_synsets, group_synsets) -> float: + return max( + (path_similarity_cached(ws, gs) for ws in word_synsets for gs in group_synsets), + default=0.0, + ) + + +WORDNET_GROUPS: Dict[str, List] | None = None + + +def get_groups() -> Dict[str, List]: + global WORDNET_GROUPS + if WORDNET_GROUPS is None: + WORDNET_GROUPS = build_wordnet_groups() + return WORDNET_GROUPS + +def match_group(word_synsets) -> str: + best_group = "" + best_score = 0.0 + + for key, synsets in get_groups().items(): + score = max_similarity(word_synsets, synsets) + if score > SIMILARITY_THRESHOLD and score > best_score: + best_score = score + best_group = key + + return best_group + + +# def tokenize_header(text: str) -> Iterable[str]: +# clean = text.translate(str.maketrans('', '', string.punctuation)) +# return clean.strip().split() +def tokenize_header(text) -> Iterable[str]: + # if list transform to string + if isinstance(text, list): + text = " ".join(map(str, text)) + elif text is None: + text = "" + clean = text.translate(str.maketrans('', '', string.punctuation)) + return clean.strip().split() + +def label_text(text: str) -> List[str]: + labels: List[str] = [] + for token in tokenize_header(text): + synsets = get_synsets(token) + if synsets: + grp = match_group(synsets) + if grp and grp not in labels: + labels.append(grp) + return labels +# def extract_categories(repo_data, repository_metadata: Result): +# """ +# Function that adds category information extracted using header information +# Parameters +# ---------- +# @param repo_data: data to use the header analysis +# @param repository_metadata: Result object with the results found so far in the repo + +# Returns +# ------- +# @return Result with the information added. +# """ +# logging.info("Extracting information using headers") +# if repo_data is None or repo_data == "" or len(repo_data) == 0: +# return repository_metadata, [] +# try: +# data, none_header_content = extract_header_content(repo_data) +# logging.info('Labeling headers.') +# if data.empty: +# logging.warning("File to analyze has no headers") +# return repository_metadata, [repo_data] +# data['Group'] = data['Header'].apply(lambda row: label_header(row)) +# data['GroupParent'] = data['ParentHeader'].apply(lambda row: label_parent_headers(row)) +# for i in data.index: +# if len(data['Group'][i]) == 0 and len(data['GroupParent'][i]) > 0: +# data.at[i, 'Group'] = data['GroupParent'][i] +# data = data.drop(columns=['GroupParent']) +# if len(data['Group'].iloc[0]) == 0: +# # data['Group'].iloc[0] = ['unknown'] +# data.loc[0, 'Group'] = ['unknown'] +# groups = data.apply(lambda x: pd.Series(x['Group']), axis=1).stack().reset_index(level=1, drop=True) + +# groups.name = 'Group' +# data = data.drop('Group', axis=1).join(groups) +# if data['Group'].iloc[0] == 'unknown': +# # data['Group'].iloc[0] = np.NaN +# data.loc[0, 'Group'] = np.nan + +# # to json +# group = data.loc[(data['Group'] != 'None') & pd.notna(data['Group'])] +# group.rename(columns={'Content': constants.PROP_VALUE}, inplace=True) +# group.rename(columns={'Header': constants.PROP_ORIGINAL_HEADER}, inplace=True) +# group.rename(columns={'ParentHeader': constants.PROP_PARENT_HEADER}, inplace=True) +# for index, row in group.iterrows(): +# source = "" +# if constants.CAT_README_URL in repository_metadata.results.keys(): +# source = repository_metadata.results[constants.CAT_README_URL][0] +# source = source[constants.PROP_RESULT][constants.PROP_VALUE] +# parent_header = "" +# if row[constants.PROP_PARENT_HEADER] != "": +# parent_header = row.loc[constants.PROP_PARENT_HEADER] +# result = { +# constants.PROP_VALUE: row.loc[constants.PROP_VALUE], +# constants.PROP_TYPE: constants.TEXT_EXCERPT, +# constants.PROP_ORIGINAL_HEADER: row.loc[constants.PROP_ORIGINAL_HEADER] +# } +# if parent_header != "" and len(parent_header) > 0: +# result[constants.PROP_PARENT_HEADER] = parent_header +# if source != "": +# repository_metadata.add_result(row.Group, result, 1, constants.TECHNIQUE_HEADER_ANALYSIS, source) +# else: +# repository_metadata.add_result(row.Group, result, 1, constants.TECHNIQUE_HEADER_ANALYSIS) + +# # strings without tag (they will be classified) +# string_list = data.loc[data['Group'].isna(), ['Content']].values.squeeze().tolist() +# if type(string_list) != list: +# string_list = [string_list] +# if none_header_content is not None and none_header_content != "": +# string_list.append(none_header_content.strip()) +# logging.info("Header information extracted.") +# return repository_metadata, string_list +# except Exception as e: +# logging.error("Error while extracting headers: ", str(e)) +# return repository_metadata, [repo_data] + +def extract_categories(repo_data: str, repository_metadata: Result) -> Tuple[Result, List[str]]: logging.info("Extracting information using headers") - if repo_data is None or repo_data == "" or len(repo_data) == 0: + + if not repo_data: return repository_metadata, [] + try: - data, none_header_content = extract_header_content(repo_data) - logging.info('Labeling headers.') - if data.empty: + df, none_header_content = extract_header_content(repo_data) + + if df.empty: logging.warning("File to analyze has no headers") return repository_metadata, [repo_data] - data['Group'] = data['Header'].apply(lambda row: label_header(row)) - data['GroupParent'] = data['ParentHeader'].apply(lambda row: label_parent_headers(row)) - for i in data.index: - if len(data['Group'][i]) == 0 and len(data['GroupParent'][i]) > 0: - data.at[i, 'Group'] = data['GroupParent'][i] - data = data.drop(columns=['GroupParent']) - if len(data['Group'].iloc[0]) == 0: - data['Group'].iloc[0] = ['unknown'] - groups = data.apply(lambda x: pd.Series(x['Group']), axis=1).stack().reset_index(level=1, drop=True) - - groups.name = 'Group' - data = data.drop('Group', axis=1).join(groups) - if data['Group'].iloc[0] == 'unknown': - data['Group'].iloc[0] = np.NaN - - # to json - group = data.loc[(data['Group'] != 'None') & pd.notna(data['Group'])] - group.rename(columns={'Content': constants.PROP_VALUE}, inplace=True) - group.rename(columns={'Header': constants.PROP_ORIGINAL_HEADER}, inplace=True) - group.rename(columns={'ParentHeader': constants.PROP_PARENT_HEADER}, inplace=True) - for index, row in group.iterrows(): - source = "" - if constants.CAT_README_URL in repository_metadata.results.keys(): - source = repository_metadata.results[constants.CAT_README_URL][0] - source = source[constants.PROP_RESULT][constants.PROP_VALUE] - parent_header = "" - if row[constants.PROP_PARENT_HEADER] != "": - parent_header = row.loc[constants.PROP_PARENT_HEADER] + + df['Group'] = df['Header'].map(label_text) + df['ParentGroup'] = df['ParentHeader'].fillna('').map(label_text) + + df.loc[df['Group'].str.len() == 0, 'Group'] = df['ParentGroup'] + df.drop(columns=['ParentGroup'], inplace=True) + + if not df.iloc[0]['Group']: + df.loc[df.index[0], 'Group'] = ['unknown'] + + df = df.explode('Group') + df.loc[df['Group'] == 'unknown', 'Group'] = np.nan + + valid = df[df['Group'].notna()].copy() + valid.rename(columns={ + 'Content': constants.PROP_VALUE, + 'Header': constants.PROP_ORIGINAL_HEADER, + 'ParentHeader': constants.PROP_PARENT_HEADER, + }, inplace=True) + + source = None + if constants.CAT_README_URL in repository_metadata.results: + source = repository_metadata.results[constants.CAT_README_URL][0] + source = source[constants.PROP_RESULT][constants.PROP_VALUE] + + logging.info("Extracting information using headers - iterating over valid entries") + logging.info("Valid rows: %s", len(valid)) + + for _, row in valid.iterrows(): result = { - constants.PROP_VALUE: row.loc[constants.PROP_VALUE], + constants.PROP_VALUE: row[constants.PROP_VALUE], constants.PROP_TYPE: constants.TEXT_EXCERPT, - constants.PROP_ORIGINAL_HEADER: row.loc[constants.PROP_ORIGINAL_HEADER] + constants.PROP_ORIGINAL_HEADER: row[constants.PROP_ORIGINAL_HEADER], } - if parent_header != "" and len(parent_header) > 0: - result[constants.PROP_PARENT_HEADER] = parent_header - if source != "": - repository_metadata.add_result(row.Group, result, 1, constants.TECHNIQUE_HEADER_ANALYSIS, source) - else: - repository_metadata.add_result(row.Group, result, 1, constants.TECHNIQUE_HEADER_ANALYSIS) - - # strings without tag (they will be classified) - string_list = data.loc[data['Group'].isna(), ['Content']].values.squeeze().tolist() - if type(string_list) != list: - string_list = [string_list] - if none_header_content is not None and none_header_content != "": - string_list.append(none_header_content.strip()) - logging.info("Header information extracted.") - return repository_metadata, string_list - except Exception as e: - logging.error("Error while extracting headers: ", str(e)) + + if row[constants.PROP_PARENT_HEADER]: + result[constants.PROP_PARENT_HEADER] = row[constants.PROP_PARENT_HEADER] + + repository_metadata.add_result( + row['Group'], + result, + 1, + constants.TECHNIQUE_HEADER_ANALYSIS, + source, + ) + + leftovers = df[df['Group'].isna()]['Content'].tolist() + if none_header_content: + leftovers.append(none_header_content.strip()) + + return repository_metadata, leftovers + + except Exception: + logging.exception("Error while extracting headers") return repository_metadata, [repo_data] + + +def build_wordnet_groups() -> Dict[str, List]: + """Build WordNet groups lazily.""" + g: Dict[str, List] = {} + + g[constants.CAT_CITATION] = [ + Word("citation").synsets[3], + Word("reference").synsets[1], + Word("cite").synsets[3], + ] + + g[constants.CAT_ACKNOWLEDGEMENT] = [Word("acknowledgement").synsets[0]] + + g[constants.CAT_RUN] = [ + Word("run").synsets[9], + Word("run").synsets[34], + Word("execute").synsets[4], + ] + + g[constants.CAT_INSTALLATION] = [ + Word("installation").synsets[0], + Word("install").synsets[0], + Word("setup").synsets[1], + Word("prepare").synsets[0], + Word("preparation").synsets[0], + Word("manual").synsets[0], + Word("guide").synsets[2], + Word("guide").synsets[9], + ] + + g[constants.CAT_DOWNLOAD] = [Word("download").synsets[0]] + + g[constants.CAT_REQUIREMENTS] = [ + Word("requirement").synsets[2], + Word("prerequisite").synsets[0], + Word("prerequisite").synsets[1], + Word("dependency").synsets[0], + Word("dependent").synsets[0], + ] + + g[constants.CAT_CONTACT] = [Word("contact").synsets[9]] + + g[constants.CAT_DESCRIPTION] = [ + Word("description").synsets[0], + Word("description").synsets[1], + Word("introduction").synsets[3], + Word("introduction").synsets[6], + Word("basics").synsets[0], + Word("initiation").synsets[1], + Word("summary").synsets[0], + Word("summary").synsets[2], + ] + + g[constants.CAT_CONTRIBUTORS] = [Word("contributor").synsets[0]] + g[constants.CAT_CONTRIBUTING_GUIDELINES] = [Word("contributing").synsets[1]] + g[constants.CAT_DOCUMENTATION] = [Word("documentation").synsets[1]] + g[constants.CAT_LICENSE] = [Word("license").synsets[3], Word("license").synsets[0]] + + g[constants.CAT_USAGE] = [ + Word("usage").synsets[0], + Word("example").synsets[0], + Word("example").synsets[5], + Word("demo").synsets[1], + Word("tutorial").synsets[0], + Word("tutorial").synsets[1], + Word("start").synsets[0], + Word("start").synsets[4], + Word("started").synsets[0], + Word("started").synsets[1], + Word("started").synsets[7], + Word("started").synsets[8], + ] + + g[constants.CAT_FAQ] = [ + Word("errors").synsets[5], + Word("problems").synsets[0], + Word("problems").synsets[2], + Word("faq").synsets[0], + ] + + g[constants.CAT_SUPPORT] = [ + Word("support").synsets[7], + Word("help").synsets[0], + Word("help").synsets[9], + Word("report").synsets[0], + Word("report").synsets[6], + ] + + return g diff --git a/src/somef_core/parser/authors_parser 2.py b/src/somef_core/parser/authors_parser 2.py new file mode 100644 index 0000000..0a8a2f1 --- /dev/null +++ b/src/somef_core/parser/authors_parser 2.py @@ -0,0 +1,81 @@ +import re +from ..utils import constants + +def parse_author_file(author_str): + """ + Process a text with possible authors from markdown-style AUTHORS files. + Filters and extracts only lines that match expected person or organization patterns. + """ + if not author_str: + return [] + + author_str = re.sub(r'\{[^}]*\}', '', author_str, flags=re.DOTALL) + + authors = [] + lines = author_str.splitlines() + + for i, line in enumerate(lines): + line = line.replace("\t", " ").strip() + next_line = lines[i + 1].strip() if i + 1 < len(lines) else "" + email_match = re.search(r'<[^<>@ ]+@[^<>@ ]+\.[^<>@ ]+>', line) + + if ( + not line or + line.startswith("#") or + line.startswith("*") or + line.startswith("=") or + (line[0].islower() and not email_match) or + re.match(r'^\s*\{.*\}\s*$', line) or + re.match(r'^https?://', line) or + len(re.findall(r'[A-Za-z]', line)) < 2 or + ( + line.endswith(".") + and not re.match(r'^([A-Z][a-zA-Z0-9&\-\.]+(?:\s+[A-Z][a-zA-Z0-9&\-\.]+){0,3})\.$', line) + and not re.search(constants.REGEXP_LTD_INC, line, re.IGNORECASE) + ) or + line.endswith(",") or + line.endswith(":") or + re.match(r'^[A-Z][a-z]+ *:$', line) or + re.match(r"^[=\-*]{2,}$", next_line) + ): + continue + + email_match = re.search(r'<(.*?)>', line) + email = email_match.group(1) if email_match else None + name_part = line[:email_match.start()].strip() if email_match else line + + name_part = re.sub(r'\(.*?\)', '', name_part) + + parts = name_part.split('-') + if len(parts) > 1 and parts[0].strip() == "": + name_part = parts[1].strip() + else: + name_part = parts[0].strip() + + name_words = name_part.split() + + if re.search(constants.REGEXP_LTD_INC, name_part, re.IGNORECASE): + raw_author = { + "type": "Organization", + "name": name_part, + "value": name_part + } + if email: + raw_author["email"] = email + authors.append(raw_author) + continue + + if email or len(name_words) >= 2 and len(name_words) <= 4: + raw_author = { + "type": "Person", + "name": name_part, + "value": name_part, + "given_name": name_words[0] + } + if len(name_words) > 1: + raw_author["last_name"] = " ".join(name_words[1:]) + if email: + raw_author["email"] = email + authors.append(raw_author) + + return authors \ No newline at end of file diff --git a/src/somef_core/parser/authors_parser.py b/src/somef_core/parser/authors_parser.py new file mode 100644 index 0000000..0a8a2f1 --- /dev/null +++ b/src/somef_core/parser/authors_parser.py @@ -0,0 +1,81 @@ +import re +from ..utils import constants + +def parse_author_file(author_str): + """ + Process a text with possible authors from markdown-style AUTHORS files. + Filters and extracts only lines that match expected person or organization patterns. + """ + if not author_str: + return [] + + author_str = re.sub(r'\{[^}]*\}', '', author_str, flags=re.DOTALL) + + authors = [] + lines = author_str.splitlines() + + for i, line in enumerate(lines): + line = line.replace("\t", " ").strip() + next_line = lines[i + 1].strip() if i + 1 < len(lines) else "" + email_match = re.search(r'<[^<>@ ]+@[^<>@ ]+\.[^<>@ ]+>', line) + + if ( + not line or + line.startswith("#") or + line.startswith("*") or + line.startswith("=") or + (line[0].islower() and not email_match) or + re.match(r'^\s*\{.*\}\s*$', line) or + re.match(r'^https?://', line) or + len(re.findall(r'[A-Za-z]', line)) < 2 or + ( + line.endswith(".") + and not re.match(r'^([A-Z][a-zA-Z0-9&\-\.]+(?:\s+[A-Z][a-zA-Z0-9&\-\.]+){0,3})\.$', line) + and not re.search(constants.REGEXP_LTD_INC, line, re.IGNORECASE) + ) or + line.endswith(",") or + line.endswith(":") or + re.match(r'^[A-Z][a-z]+ *:$', line) or + re.match(r"^[=\-*]{2,}$", next_line) + ): + continue + + email_match = re.search(r'<(.*?)>', line) + email = email_match.group(1) if email_match else None + name_part = line[:email_match.start()].strip() if email_match else line + + name_part = re.sub(r'\(.*?\)', '', name_part) + + parts = name_part.split('-') + if len(parts) > 1 and parts[0].strip() == "": + name_part = parts[1].strip() + else: + name_part = parts[0].strip() + + name_words = name_part.split() + + if re.search(constants.REGEXP_LTD_INC, name_part, re.IGNORECASE): + raw_author = { + "type": "Organization", + "name": name_part, + "value": name_part + } + if email: + raw_author["email"] = email + authors.append(raw_author) + continue + + if email or len(name_words) >= 2 and len(name_words) <= 4: + raw_author = { + "type": "Person", + "name": name_part, + "value": name_part, + "given_name": name_words[0] + } + if len(name_words) > 1: + raw_author["last_name"] = " ".join(name_words[1:]) + if email: + raw_author["email"] = email + authors.append(raw_author) + + return authors \ No newline at end of file diff --git a/src/somef_core/parser/bower_parser 2.py b/src/somef_core/parser/bower_parser 2.py new file mode 100644 index 0000000..1479388 --- /dev/null +++ b/src/somef_core/parser/bower_parser 2.py @@ -0,0 +1,183 @@ +import json +import logging +import os +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_bower_json_file(file_path, metadata_result: Result, source): + """ + + Parameters + ---------- + file_path: path of the bower file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + + """ + try: + if Path(file_path).name.lower() in ["bower.json"]: + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "bower.json", + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + data = json.load(file) + + if "name" in data: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "homepage" in data: + home = data["homepage"] + if home and home.strip(): + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": data["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.RELEASE, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "authors" in data: + authors_data = data["authors"] + if isinstance(authors_data, str): + authors_list = [a.strip() for a in authors_data.split(",") if a.strip()] + elif isinstance(authors_data, list): + authors_list = [] + for a in authors_data: + if isinstance(a, str): + authors_list.extend([s.strip() for s in a.split(",") if s.strip()]) + elif isinstance(a, dict): + name = a.get("name", "") + email = f" <{a['email']}>" if "email" in a else "" + authors_list.append(f"{name}{email}".strip()) + else: + authors_list = [] + + for aut in authors_list: + # "value": data["authors"], + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "value": aut, + "type": constants.AGENT + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + metadata_result.add_result( + constants.CAT_LICENSE, + { + "value": data["license"], + "type": constants.LICENSE + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + if "dependencies" in data and isinstance(data["dependencies"], dict): + for name, version in data["dependencies"].items(): + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "devDependencies" in data and isinstance(data["devDependencies"], dict): + for name, version in data["devDependencies"].items(): + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "dev" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + for keyword in data["keywords"]: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing bower.json from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/bower_parser.py b/src/somef_core/parser/bower_parser.py new file mode 100644 index 0000000..1479388 --- /dev/null +++ b/src/somef_core/parser/bower_parser.py @@ -0,0 +1,183 @@ +import json +import logging +import os +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_bower_json_file(file_path, metadata_result: Result, source): + """ + + Parameters + ---------- + file_path: path of the bower file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + + """ + try: + if Path(file_path).name.lower() in ["bower.json"]: + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "bower.json", + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + data = json.load(file) + + if "name" in data: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "homepage" in data: + home = data["homepage"] + if home and home.strip(): + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": data["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.RELEASE, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "authors" in data: + authors_data = data["authors"] + if isinstance(authors_data, str): + authors_list = [a.strip() for a in authors_data.split(",") if a.strip()] + elif isinstance(authors_data, list): + authors_list = [] + for a in authors_data: + if isinstance(a, str): + authors_list.extend([s.strip() for s in a.split(",") if s.strip()]) + elif isinstance(a, dict): + name = a.get("name", "") + email = f" <{a['email']}>" if "email" in a else "" + authors_list.append(f"{name}{email}".strip()) + else: + authors_list = [] + + for aut in authors_list: + # "value": data["authors"], + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "value": aut, + "type": constants.AGENT + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + metadata_result.add_result( + constants.CAT_LICENSE, + { + "value": data["license"], + "type": constants.LICENSE + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + if "dependencies" in data and isinstance(data["dependencies"], dict): + for name, version in data["dependencies"].items(): + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "devDependencies" in data and isinstance(data["devDependencies"], dict): + for name, version in data["devDependencies"].items(): + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "dev" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + for keyword in data["keywords"]: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing bower.json from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/cabal_parser 2.py b/src/somef_core/parser/cabal_parser 2.py new file mode 100644 index 0000000..74ed7bd --- /dev/null +++ b/src/somef_core/parser/cabal_parser 2.py @@ -0,0 +1,221 @@ +import os +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..regular_expressions import detect_license_spdx +from ..utils import constants + +def parse_cabal_file(file_path, metadata_result: Result, source): + """ + Parse a .cabal file and extract relevant metadata. + + Parameters + ---------- + file_path: path of the cabal file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + """ + + try: + if file_path.endswith('.cabal'): + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": Path(file_path).name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + name_match = re.search(r'name:\s*(.*)', content, re.IGNORECASE) + if name_match: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(r'version:\s*(.*)', content, re.IGNORECASE) + if version_match: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + # description_match = re.search(r'description:\s*(.*)', content, re.IGNORECASE) + cleaned_content = content.replace('\r\n', '\n').replace('\r', '\n') + description_regex = re.compile( + r'description:\s*(.*?)(?=\n\S|\Z)', + re.IGNORECASE | re.DOTALL + ) + + description_match = description_regex.search(cleaned_content) + synopsis_match = re.search(r'synopsis:\s*(.*)', content, re.IGNORECASE) + if description_match: + + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if synopsis_match: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": synopsis_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + homepage_match = re.search(r'homepage:\s*(.*)', content, re.IGNORECASE) + if homepage_match: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": homepage_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + stability_match = re.search(r'stability:\s*(.*)', content, re.IGNORECASE) + if stability_match: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": stability_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + bug_reports_match = re.search(r'bug-reports:\s*(.*)', content, re.IGNORECASE) + if bug_reports_match: + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": bug_reports_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + license_match = re.search(r'license:\s*(.*)', content, re.IGNORECASE) + if license_match: + license_value = license_match.group(1) + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'Ruby') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + library_section_match = re.search(r'library\s*\n(.*?)(?=\n\S|\Z)', content, re.DOTALL | re.IGNORECASE) + if library_section_match: + library_content = library_section_match.group(1) + + build_depends_match = re.search( + r'build-depends:\s*(.*?)(?=\n\s*(?:[A-Za-z0-9_-]+\s*:|if\s|\Z))', + library_content, + re.DOTALL + ) + # build_depends_match = re.search(r'build-depends:\s*(.*?)(?=\n\s*\w+:|\Z)', library_content, re.DOTALL) + if build_depends_match: + build_depends_content = build_depends_match.group(1) + + dependencies = re.split(r'[,\n]', build_depends_content) + + for dep_line in dependencies: + dep_line = dep_line.strip() + if dep_line and not dep_line.startswith(','): + + dep_match = re.match(r'^([a-zA-Z0-9-_]+)\s*(.*?)$', dep_line) + if dep_match: + name = dep_match.group(1) + version_constraint = dep_match.group(2).strip() if dep_match.group(2) else "any" + req = f"{name}: {version_constraint}" if version_constraint != "any" else name + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version_constraint, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/cabal_parser.py b/src/somef_core/parser/cabal_parser.py new file mode 100644 index 0000000..74ed7bd --- /dev/null +++ b/src/somef_core/parser/cabal_parser.py @@ -0,0 +1,221 @@ +import os +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..regular_expressions import detect_license_spdx +from ..utils import constants + +def parse_cabal_file(file_path, metadata_result: Result, source): + """ + Parse a .cabal file and extract relevant metadata. + + Parameters + ---------- + file_path: path of the cabal file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + """ + + try: + if file_path.endswith('.cabal'): + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": Path(file_path).name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + name_match = re.search(r'name:\s*(.*)', content, re.IGNORECASE) + if name_match: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(r'version:\s*(.*)', content, re.IGNORECASE) + if version_match: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + # description_match = re.search(r'description:\s*(.*)', content, re.IGNORECASE) + cleaned_content = content.replace('\r\n', '\n').replace('\r', '\n') + description_regex = re.compile( + r'description:\s*(.*?)(?=\n\S|\Z)', + re.IGNORECASE | re.DOTALL + ) + + description_match = description_regex.search(cleaned_content) + synopsis_match = re.search(r'synopsis:\s*(.*)', content, re.IGNORECASE) + if description_match: + + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if synopsis_match: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": synopsis_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + homepage_match = re.search(r'homepage:\s*(.*)', content, re.IGNORECASE) + if homepage_match: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": homepage_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + stability_match = re.search(r'stability:\s*(.*)', content, re.IGNORECASE) + if stability_match: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": stability_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + bug_reports_match = re.search(r'bug-reports:\s*(.*)', content, re.IGNORECASE) + if bug_reports_match: + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": bug_reports_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + license_match = re.search(r'license:\s*(.*)', content, re.IGNORECASE) + if license_match: + license_value = license_match.group(1) + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'Ruby') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + library_section_match = re.search(r'library\s*\n(.*?)(?=\n\S|\Z)', content, re.DOTALL | re.IGNORECASE) + if library_section_match: + library_content = library_section_match.group(1) + + build_depends_match = re.search( + r'build-depends:\s*(.*?)(?=\n\s*(?:[A-Za-z0-9_-]+\s*:|if\s|\Z))', + library_content, + re.DOTALL + ) + # build_depends_match = re.search(r'build-depends:\s*(.*?)(?=\n\s*\w+:|\Z)', library_content, re.DOTALL) + if build_depends_match: + build_depends_content = build_depends_match.group(1) + + dependencies = re.split(r'[,\n]', build_depends_content) + + for dep_line in dependencies: + dep_line = dep_line.strip() + if dep_line and not dep_line.startswith(','): + + dep_match = re.match(r'^([a-zA-Z0-9-_]+)\s*(.*?)$', dep_line) + if dep_match: + name = dep_match.group(1) + version_constraint = dep_match.group(2).strip() if dep_match.group(2) else "any" + req = f"{name}: {version_constraint}" if version_constraint != "any" else name + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version_constraint, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/codemeta_parser 2.py b/src/somef_core/parser/codemeta_parser 2.py new file mode 100644 index 0000000..6c6098a --- /dev/null +++ b/src/somef_core/parser/codemeta_parser 2.py @@ -0,0 +1,695 @@ +import json +import logging +from ..process_results import Result +from ..utils import constants +import re + + +def parse_keywords(keywords_data): + """ + Parse keywords from codemeta.json file + + Parameters + ---------- + keywords_data: str or list + The keywords data from codemeta.json, can be a comma-separated string or a list + + Returns + ------- + list + List of processed keywords + """ + processed_keywords = [] + if isinstance(keywords_data, str): + for k in keywords_data.split(","): + k = k.strip() + if k: + processed_keywords.append(k) + return processed_keywords + elif isinstance(keywords_data, list): + for item in keywords_data: + if isinstance(item, str): + sub_parts = item.split(",") + for sub_part in sub_parts: + processed_keywords.append(sub_part.strip()) + else: + processed_keywords.append(str(item).strip()) + return processed_keywords + return processed_keywords + + +def parse_license(license_data): + """ + Parse license information from codemeta.json + + Parameters + ---------- + license_data: dict or str + The license data from codemeta.json + + Returns + ------- + dict or None + Processed license information with keys: name, url, identifier, spdx_id + """ + license_info = {} + if isinstance(license_data, dict): + license_info["name"] = license_data.get("name") + license_info["url"] = license_data.get("url") + license_info["identifier"] = license_data.get("identifier") + + identifier = license_info.get("identifier", "") + if "spdx.org/licenses/" in identifier: + spdx_id = identifier.split("spdx.org/licenses/")[-1].split("/")[0] + license_info["spdx_id"] = spdx_id + elif isinstance(license_data, str): + license_info["name"] = license_data + license_info["identifier"] = f"https://spdx.org/licenses/{license_data}" + license_info["spdx_id"] = license_data + else: + return None + return license_info + + +def parse_software_requirements(requirements_data): + """ + Parse software requirements information from codemeta.json + + Parameters + ---------- + requirements_data: list or str + The software requirements data from codemeta.json + + Returns + ------- + list + """ + requirements = [] + + if isinstance(requirements_data, str): + requirements_data = [requirements_data] + + if isinstance(requirements_data, list): + for req in requirements_data: + if isinstance(req, str): + original = req.strip() + + match = re.match(r'^([a-zA-Z0-9_.\-]+)([<>=!~].*)?$', original) + if match: + name = match.group(1) + version = match.group(2).strip() if match.group(2) else None + requirements.append({ + "value": original, + # "name": name, + # "version": version + **({"name": name} if name else {}), + **({"version": version} if version else {}) + }) + else: + requirements.append({ + "value": original + }) + elif isinstance(req, dict): + # Handle structured object format + name = req.get("name") or req.get("identifier") + version = req.get("version") + identifier = req.get("identifier") + + if name: + requirement_dict = { + "value": name, + "name": name + } + + if version: + requirement_dict["version"] = version + requirement_dict["value"] = f"{name}=={version}" if version else name + + if identifier and identifier != name: + requirement_dict["identifier"] = identifier + + requirements.append(requirement_dict) + + return requirements + + +def parse_referenced_publication(reference_data): + """ + Parse referenced publication information from codemeta.json + + Parameters + ---------- + reference_data: dict + The reference publication data from codemeta.json + + Returns + ------- + dict or None + """ + if isinstance(reference_data, dict): + return { + "title": reference_data.get("name") or reference_data.get("title"), + "author": reference_data.get("author"), + "url": reference_data.get("url"), + "date_published": reference_data.get("datePublished"), + "identifier": reference_data.get("identifier") + } + return None + + +def parse_funding(funding_data): + """ + Parse funding information from codemeta.json + + Parameters + ---------- + funding_data: dict, str + The funding data from codemeta.json + + Returns + ------- + dict or None + """ + if isinstance(funding_data, dict): + funder_name = None + if "funder" in funding_data: + funder = funding_data["funder"] + if isinstance(funder, dict): + funder_name = funder.get("name") + + return { + "funder": funder_name, + "funding": funding_data.get("fundingIdentifier") + } + elif isinstance(funding_data, str): + return { + "funder": None, + "funding": funding_data + } + + return None + +def parse_programming_language(language_data): + """ + Parse programming language information from codemeta.json + + Parameters + ---------- + language_data: dict or str + The programming language data from codemeta.json + + Returns + ------- + dict or None + Processed programming language information + """ + if isinstance(language_data, dict): + name = language_data.get("name") + version = language_data.get("version") + url = language_data.get("url") + + if name: + lang_info = { + "name": name, + "value": name, + "type": constants.LANGUAGE + # "version": version if version is not None else None + } + if version: + lang_info["version"] = version + + if url: + lang_info["url"] = url + + return lang_info + + elif isinstance(language_data, str): + return { + "name": language_data, + "value": language_data, + "type": constants.LANGUAGE + # , + # "version": None + } + + return None + +def parse_codemeta_json_file(file_path, metadata_result: Result, source): + """ + + Parameters + ---------- + file_path: path of the package file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the codemeta file (URL) + + Returns + ------- + + """ + print(f"CODEMETA PARSER - Processing file: {file_path}") + print(f"CODEMETA PARSER - Source: {source}") + + try: + with open(file_path, 'r', encoding='utf-8') as file: + data = json.load(file) + + if "applicationCategory" in data: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": data["applicationCategory"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareVersion" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["softwareVersion"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "codeRepository" in data: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": data["codeRepository"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "issueTracker" in data: + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": data["issueTracker"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dateCreated" in data: + date_created = data["dateCreated"] + if date_created: + metadata_result.add_result( + constants.CAT_DATE_CREATED, + { + "value": date_created, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dateModified" in data: + date_modified = data["dateModified"] + if date_modified: + metadata_result.add_result( + constants.CAT_DATE_UPDATED, + { + "value": date_modified, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "datePublished" in data: + date_published = data["datePublished"] + if date_published: + metadata_result.add_result( + constants.CAT_DATE_PUBLISHED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "downloadUrl" in data: + metadata_result.add_result( + constants.CAT_DOWNLOAD_URL, + { + "value": data["downloadUrl"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "name" in data: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "contIntegration" in data: + metadata_result.add_result( + constants.CAT_CONTINUOUS_INTEGRATION, + { + "value": data["contIntegration"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + keywords = parse_keywords(data['keywords']) + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keywords, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "referencePublication" in data: + ref_publications = data["referencePublication"] + if isinstance(ref_publications, list): + + for pub in ref_publications: + pub_data = parse_referenced_publication(pub) + if pub_data: + + result_dict = { + "value": pub_data.get("title", ""), + "title": pub_data.get("title", ""), + "type": constants.SCHOLARLY_ARTICLE + } + + if pub_data.get("url"): + result_dict["url"] = pub_data.get("url") + + if pub_data.get("date_published"): + result_dict["date_published"] = pub_data.get("date_published") + + if pub_data.get("identifier"): + result_dict["doi"] = pub_data.get("identifier") + + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(ref_publications, dict): + + pub_data = parse_referenced_publication(ref_publications) + if pub_data: + result_dict = { + "value": pub_data.get("title", ""), + "title": pub_data.get("title", ""), + "type": constants.SCHOLARLY_ARTICLE + } + + if pub_data.get("url"): + result_dict["url"] = pub_data.get("url") + + if pub_data.get("date_published"): + result_dict["date_published"] = pub_data.get("date_published") + + if pub_data.get("identifier"): + result_dict["doi"] = pub_data.get("identifier") + + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + { + "value": data["referencePublication"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "funding" in data: + funding_data = data["funding"] + if isinstance(funding_data, list): + for fund in funding_data: + fund_info = parse_funding(fund) + if fund_info: + metadata_result.add_result( + constants.CAT_FUNDING, + { + "funder": fund_info.get("funder", ""), + "funding": fund_info.get("funding", ""), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(funding_data, dict): + fund_info = parse_funding(funding_data) + if fund_info: + metadata_result.add_result( + constants.CAT_FUNDING, + { + "funder": fund_info.get("funder", ""), + "funding": fund_info.get("funding", ""), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "developmentStatus" in data: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": data["developmentStatus"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "identifier" in data: + metadata_result.add_result( + constants.CAT_IDENTIFIER, + { + "value": data["identifier"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "readme" in data: + metadata_result.add_result( + constants.CAT_README_URL, + { + "value": data["readme"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "author" in data: + authors = data["author"] + if isinstance(authors, list): + for author in authors: + if isinstance(author, dict): + author_name = "" + if "givenName" in author and "familyName" in author: + author_name = f"{author['givenName']} {author['familyName']}" + elif "name" in author: + author_name = author["name"] + + if author_name: + author_info = { + "value": author_name, + "type": constants.STRING + } + + if "email" in author: + author_info["email"] = author["email"] + + if "affiliation" in author: + if isinstance(author["affiliation"], dict) and "name" in author["affiliation"]: + author_info["affiliation"] = author["affiliation"]["name"] + elif isinstance(author["affiliation"], str): + author_info["affiliation"] = author["affiliation"] + + identifier = author.get("identifier") or author.get("@id") + if identifier: + author_info["identifier"] = identifier + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(authors, dict): + author = authors + author_name = "" + if "givenName" in author and "familyName" in author: + author_name = f"{author['givenName']} {author['familyName']}" + elif "name" in author: + author_name = author["name"] + + if author_name: + author_info = { + "value": author_name, + "type": constants.STRING + } + + if "email" in author: + author_info["email"] = author["email"] + + if "affiliation" in author and "name" in author["affiliation"]: + author_info["affiliation"] = author["affiliation"]["name"] + + if "identifier" in author: + author_info["identifier"] = author["identifier"] + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + license_info = parse_license(data["license"]) + if license_info: + result_dict = { + "value": license_info.get("name", ""), + "type": constants.LICENSE + } + + if license_info.get("url"): + result_dict["url"] = license_info["url"] + if license_info.get("identifier"): + result_dict["identifier"] = license_info["identifier"] + if license_info.get("spdx_id"): + result_dict["spdx_id"] = license_info["spdx_id"] + + metadata_result.add_result( + constants.CAT_LICENSE, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareRequirements" in data: + requirements = parse_software_requirements(data["softwareRequirements"]) + for requirement in requirements: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": requirement.get("value"), + # "name": requirement.get("name"), + # "version": requirement.get("version"), + **({"name": requirement["name"]} if "name" in requirement else {}), + **({"version": requirement["version"]} if "version" in requirement else {}), + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if "programmingLanguage" in data: + programming_language = data["programmingLanguage"] + if isinstance(programming_language, list): + for lang in programming_language: + lang_info = parse_programming_language(lang) + if lang_info: + metadata_result.add_result( + constants.CAT_PROGRAMMING_LANGUAGES, + lang_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + lang_info = parse_programming_language(programming_language) + if lang_info: + metadata_result.add_result( + constants.CAT_PROGRAMMING_LANGUAGES, + lang_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing codemeta JSON file {file_path}: {str(e)}") + + return metadata_result + diff --git a/src/somef_core/parser/codemeta_parser.py b/src/somef_core/parser/codemeta_parser.py new file mode 100644 index 0000000..6c6098a --- /dev/null +++ b/src/somef_core/parser/codemeta_parser.py @@ -0,0 +1,695 @@ +import json +import logging +from ..process_results import Result +from ..utils import constants +import re + + +def parse_keywords(keywords_data): + """ + Parse keywords from codemeta.json file + + Parameters + ---------- + keywords_data: str or list + The keywords data from codemeta.json, can be a comma-separated string or a list + + Returns + ------- + list + List of processed keywords + """ + processed_keywords = [] + if isinstance(keywords_data, str): + for k in keywords_data.split(","): + k = k.strip() + if k: + processed_keywords.append(k) + return processed_keywords + elif isinstance(keywords_data, list): + for item in keywords_data: + if isinstance(item, str): + sub_parts = item.split(",") + for sub_part in sub_parts: + processed_keywords.append(sub_part.strip()) + else: + processed_keywords.append(str(item).strip()) + return processed_keywords + return processed_keywords + + +def parse_license(license_data): + """ + Parse license information from codemeta.json + + Parameters + ---------- + license_data: dict or str + The license data from codemeta.json + + Returns + ------- + dict or None + Processed license information with keys: name, url, identifier, spdx_id + """ + license_info = {} + if isinstance(license_data, dict): + license_info["name"] = license_data.get("name") + license_info["url"] = license_data.get("url") + license_info["identifier"] = license_data.get("identifier") + + identifier = license_info.get("identifier", "") + if "spdx.org/licenses/" in identifier: + spdx_id = identifier.split("spdx.org/licenses/")[-1].split("/")[0] + license_info["spdx_id"] = spdx_id + elif isinstance(license_data, str): + license_info["name"] = license_data + license_info["identifier"] = f"https://spdx.org/licenses/{license_data}" + license_info["spdx_id"] = license_data + else: + return None + return license_info + + +def parse_software_requirements(requirements_data): + """ + Parse software requirements information from codemeta.json + + Parameters + ---------- + requirements_data: list or str + The software requirements data from codemeta.json + + Returns + ------- + list + """ + requirements = [] + + if isinstance(requirements_data, str): + requirements_data = [requirements_data] + + if isinstance(requirements_data, list): + for req in requirements_data: + if isinstance(req, str): + original = req.strip() + + match = re.match(r'^([a-zA-Z0-9_.\-]+)([<>=!~].*)?$', original) + if match: + name = match.group(1) + version = match.group(2).strip() if match.group(2) else None + requirements.append({ + "value": original, + # "name": name, + # "version": version + **({"name": name} if name else {}), + **({"version": version} if version else {}) + }) + else: + requirements.append({ + "value": original + }) + elif isinstance(req, dict): + # Handle structured object format + name = req.get("name") or req.get("identifier") + version = req.get("version") + identifier = req.get("identifier") + + if name: + requirement_dict = { + "value": name, + "name": name + } + + if version: + requirement_dict["version"] = version + requirement_dict["value"] = f"{name}=={version}" if version else name + + if identifier and identifier != name: + requirement_dict["identifier"] = identifier + + requirements.append(requirement_dict) + + return requirements + + +def parse_referenced_publication(reference_data): + """ + Parse referenced publication information from codemeta.json + + Parameters + ---------- + reference_data: dict + The reference publication data from codemeta.json + + Returns + ------- + dict or None + """ + if isinstance(reference_data, dict): + return { + "title": reference_data.get("name") or reference_data.get("title"), + "author": reference_data.get("author"), + "url": reference_data.get("url"), + "date_published": reference_data.get("datePublished"), + "identifier": reference_data.get("identifier") + } + return None + + +def parse_funding(funding_data): + """ + Parse funding information from codemeta.json + + Parameters + ---------- + funding_data: dict, str + The funding data from codemeta.json + + Returns + ------- + dict or None + """ + if isinstance(funding_data, dict): + funder_name = None + if "funder" in funding_data: + funder = funding_data["funder"] + if isinstance(funder, dict): + funder_name = funder.get("name") + + return { + "funder": funder_name, + "funding": funding_data.get("fundingIdentifier") + } + elif isinstance(funding_data, str): + return { + "funder": None, + "funding": funding_data + } + + return None + +def parse_programming_language(language_data): + """ + Parse programming language information from codemeta.json + + Parameters + ---------- + language_data: dict or str + The programming language data from codemeta.json + + Returns + ------- + dict or None + Processed programming language information + """ + if isinstance(language_data, dict): + name = language_data.get("name") + version = language_data.get("version") + url = language_data.get("url") + + if name: + lang_info = { + "name": name, + "value": name, + "type": constants.LANGUAGE + # "version": version if version is not None else None + } + if version: + lang_info["version"] = version + + if url: + lang_info["url"] = url + + return lang_info + + elif isinstance(language_data, str): + return { + "name": language_data, + "value": language_data, + "type": constants.LANGUAGE + # , + # "version": None + } + + return None + +def parse_codemeta_json_file(file_path, metadata_result: Result, source): + """ + + Parameters + ---------- + file_path: path of the package file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the codemeta file (URL) + + Returns + ------- + + """ + print(f"CODEMETA PARSER - Processing file: {file_path}") + print(f"CODEMETA PARSER - Source: {source}") + + try: + with open(file_path, 'r', encoding='utf-8') as file: + data = json.load(file) + + if "applicationCategory" in data: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": data["applicationCategory"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareVersion" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["softwareVersion"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "codeRepository" in data: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": data["codeRepository"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "issueTracker" in data: + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": data["issueTracker"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dateCreated" in data: + date_created = data["dateCreated"] + if date_created: + metadata_result.add_result( + constants.CAT_DATE_CREATED, + { + "value": date_created, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dateModified" in data: + date_modified = data["dateModified"] + if date_modified: + metadata_result.add_result( + constants.CAT_DATE_UPDATED, + { + "value": date_modified, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "datePublished" in data: + date_published = data["datePublished"] + if date_published: + metadata_result.add_result( + constants.CAT_DATE_PUBLISHED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "downloadUrl" in data: + metadata_result.add_result( + constants.CAT_DOWNLOAD_URL, + { + "value": data["downloadUrl"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "name" in data: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "contIntegration" in data: + metadata_result.add_result( + constants.CAT_CONTINUOUS_INTEGRATION, + { + "value": data["contIntegration"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + keywords = parse_keywords(data['keywords']) + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keywords, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "referencePublication" in data: + ref_publications = data["referencePublication"] + if isinstance(ref_publications, list): + + for pub in ref_publications: + pub_data = parse_referenced_publication(pub) + if pub_data: + + result_dict = { + "value": pub_data.get("title", ""), + "title": pub_data.get("title", ""), + "type": constants.SCHOLARLY_ARTICLE + } + + if pub_data.get("url"): + result_dict["url"] = pub_data.get("url") + + if pub_data.get("date_published"): + result_dict["date_published"] = pub_data.get("date_published") + + if pub_data.get("identifier"): + result_dict["doi"] = pub_data.get("identifier") + + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(ref_publications, dict): + + pub_data = parse_referenced_publication(ref_publications) + if pub_data: + result_dict = { + "value": pub_data.get("title", ""), + "title": pub_data.get("title", ""), + "type": constants.SCHOLARLY_ARTICLE + } + + if pub_data.get("url"): + result_dict["url"] = pub_data.get("url") + + if pub_data.get("date_published"): + result_dict["date_published"] = pub_data.get("date_published") + + if pub_data.get("identifier"): + result_dict["doi"] = pub_data.get("identifier") + + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + metadata_result.add_result( + # constants.CAT_REF_PUBLICATION, + constants.CAT_CITATION, + { + "value": data["referencePublication"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "funding" in data: + funding_data = data["funding"] + if isinstance(funding_data, list): + for fund in funding_data: + fund_info = parse_funding(fund) + if fund_info: + metadata_result.add_result( + constants.CAT_FUNDING, + { + "funder": fund_info.get("funder", ""), + "funding": fund_info.get("funding", ""), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(funding_data, dict): + fund_info = parse_funding(funding_data) + if fund_info: + metadata_result.add_result( + constants.CAT_FUNDING, + { + "funder": fund_info.get("funder", ""), + "funding": fund_info.get("funding", ""), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "developmentStatus" in data: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": data["developmentStatus"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "identifier" in data: + metadata_result.add_result( + constants.CAT_IDENTIFIER, + { + "value": data["identifier"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "readme" in data: + metadata_result.add_result( + constants.CAT_README_URL, + { + "value": data["readme"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "author" in data: + authors = data["author"] + if isinstance(authors, list): + for author in authors: + if isinstance(author, dict): + author_name = "" + if "givenName" in author and "familyName" in author: + author_name = f"{author['givenName']} {author['familyName']}" + elif "name" in author: + author_name = author["name"] + + if author_name: + author_info = { + "value": author_name, + "type": constants.STRING + } + + if "email" in author: + author_info["email"] = author["email"] + + if "affiliation" in author: + if isinstance(author["affiliation"], dict) and "name" in author["affiliation"]: + author_info["affiliation"] = author["affiliation"]["name"] + elif isinstance(author["affiliation"], str): + author_info["affiliation"] = author["affiliation"] + + identifier = author.get("identifier") or author.get("@id") + if identifier: + author_info["identifier"] = identifier + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(authors, dict): + author = authors + author_name = "" + if "givenName" in author and "familyName" in author: + author_name = f"{author['givenName']} {author['familyName']}" + elif "name" in author: + author_name = author["name"] + + if author_name: + author_info = { + "value": author_name, + "type": constants.STRING + } + + if "email" in author: + author_info["email"] = author["email"] + + if "affiliation" in author and "name" in author["affiliation"]: + author_info["affiliation"] = author["affiliation"]["name"] + + if "identifier" in author: + author_info["identifier"] = author["identifier"] + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + license_info = parse_license(data["license"]) + if license_info: + result_dict = { + "value": license_info.get("name", ""), + "type": constants.LICENSE + } + + if license_info.get("url"): + result_dict["url"] = license_info["url"] + if license_info.get("identifier"): + result_dict["identifier"] = license_info["identifier"] + if license_info.get("spdx_id"): + result_dict["spdx_id"] = license_info["spdx_id"] + + metadata_result.add_result( + constants.CAT_LICENSE, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareRequirements" in data: + requirements = parse_software_requirements(data["softwareRequirements"]) + for requirement in requirements: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": requirement.get("value"), + # "name": requirement.get("name"), + # "version": requirement.get("version"), + **({"name": requirement["name"]} if "name" in requirement else {}), + **({"version": requirement["version"]} if "version" in requirement else {}), + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if "programmingLanguage" in data: + programming_language = data["programmingLanguage"] + if isinstance(programming_language, list): + for lang in programming_language: + lang_info = parse_programming_language(lang) + if lang_info: + metadata_result.add_result( + constants.CAT_PROGRAMMING_LANGUAGES, + lang_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + lang_info = parse_programming_language(programming_language) + if lang_info: + metadata_result.add_result( + constants.CAT_PROGRAMMING_LANGUAGES, + lang_info, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing codemeta JSON file {file_path}: {str(e)}") + + return metadata_result + diff --git a/src/somef_core/parser/composer_parser 2.py b/src/somef_core/parser/composer_parser 2.py new file mode 100644 index 0000000..d1b0794 --- /dev/null +++ b/src/somef_core/parser/composer_parser 2.py @@ -0,0 +1,217 @@ +import json +import logging +import os +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_composer_json(file_path, metadata_result: Result, source): + """ + Parse a composer.json file to extract metadata. + + Parameters + ---------- + file_path: path to the composer.json file being analyzed + metadata_result: Metadata object dictionary + source: source of the package file (URL) + + Returns + ------- + """ + try: + + if Path(file_path).name.lower() in ["composer.json"]: + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "composer.json", + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "r", encoding="utf-8") as f: + data = json.load(f) + + if "name" in data: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "homepage" in data: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": data["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.RELEASE, + "tag": data["version"] + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "authors" in data: + for author in data["authors"]: + author_data = { + "type": constants.AGENT, + "value": author.get("name", "") + } + + if "name" in author: + author_data["name"] = author["name"] + + if "email" in author: + author_data["email"] = author["email"] + + if "homepage" in author: + author_data["url"] = author["homepage"] + + if "role" in author: + author_data["role"] = author["role"] + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + license_value = data["license"] + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'JSON') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dependency_sections = ["require", "require-dev"] + for section in dependency_sections: + if section in data: + for name, version in data[section].items(): + req = f"{name}: {version}" + if section == "require-dev": + dep_type = "dev" + else: + dep_type = "runtime" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "repository" in data: + repo_data = data["repository"] + if isinstance(repo_data, str): + repo_url = repo_data + elif isinstance(repo_data, dict) and "url" in repo_data: + repo_url = repo_data["url"] + else: + repo_url = None + + if repo_url: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": repo_url, + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + for keyword in data["keywords"]: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing composer.json from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/composer_parser.py b/src/somef_core/parser/composer_parser.py new file mode 100644 index 0000000..d1b0794 --- /dev/null +++ b/src/somef_core/parser/composer_parser.py @@ -0,0 +1,217 @@ +import json +import logging +import os +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_composer_json(file_path, metadata_result: Result, source): + """ + Parse a composer.json file to extract metadata. + + Parameters + ---------- + file_path: path to the composer.json file being analyzed + metadata_result: Metadata object dictionary + source: source of the package file (URL) + + Returns + ------- + """ + try: + + if Path(file_path).name.lower() in ["composer.json"]: + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "composer.json", + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "r", encoding="utf-8") as f: + data = json.load(f) + + if "name" in data: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": data["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in data: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": data["description"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "homepage" in data: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": data["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "version" in data: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": data["version"], + "type": constants.RELEASE, + "tag": data["version"] + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "authors" in data: + for author in data["authors"]: + author_data = { + "type": constants.AGENT, + "value": author.get("name", "") + } + + if "name" in author: + author_data["name"] = author["name"] + + if "email" in author: + author_data["email"] = author["email"] + + if "homepage" in author: + author_data["url"] = author["homepage"] + + if "role" in author: + author_data["role"] = author["role"] + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in data: + license_value = data["license"] + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'JSON') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dependency_sections = ["require", "require-dev"] + for section in dependency_sections: + if section in data: + for name, version in data[section].items(): + req = f"{name}: {version}" + if section == "require-dev": + dep_type = "dev" + else: + dep_type = "runtime" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "repository" in data: + repo_data = data["repository"] + if isinstance(repo_data, str): + repo_url = repo_data + elif isinstance(repo_data, dict) and "url" in repo_data: + repo_url = repo_data["url"] + else: + repo_url = None + + if repo_url: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": repo_url, + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "keywords" in data: + for keyword in data["keywords"]: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing composer.json from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/create_excerpts.py b/src/somef_core/parser/create_excerpts.py index c4ef97b..bf0f4a2 100644 --- a/src/somef_core/parser/create_excerpts.py +++ b/src/somef_core/parser/create_excerpts.py @@ -28,43 +28,44 @@ def unmark_element(element, stream=None): __md.stripTopLevelTags = False -def split_into_excerpts(string_list): - """ - ## Function takes readme text as input and divides it into excerpts - Parameters - ---------- - string_list: input text +# def split_into_excerpts(string_list): +# """ +# ## Function takes readme text as input and divides it into excerpts +# Parameters +# ---------- +# string_list: input text - Returns - ------- - Returns the extracted excerpts - """ - divisions = [] - for text in string_list: - if text: - divisions = divisions + markdown_utils.unmark(text).splitlines() - divisions = [i for i in divisions if i] - return divisions +# Returns +# ------- +# Returns the extracted excerpts +# """ +# divisions = [] +# for text in string_list: +# if text: +# divisions = divisions + markdown_utils.unmark(text).splitlines() +# divisions = [i for i in divisions if i] +# return divisions -def create_excerpts(string_list): - """ - Function takes readme text as input and divides it into excerpts - Parameters - ---------- - string_list: Markdown text passed as input - Returns - ------- - Extracted excerpts - """ - logging.info("Splitting text into valid excerpts for classification") - string_list = markdown_utils.remove_bibtex(string_list) - divisions = mardown_parser.extract_blocks_excerpts(string_list) - logging.info("Text Successfully split.") - output = {} - for division in divisions: - original = division - division = regular_expressions.remove_links_images(division) - if len(division) > 0: - output[division] = original - return output +# def create_excerpts(string_list): +# """ +# Function takes readme text as input and divides it into excerpts +# Parameters +# ---------- +# string_list: Markdown text passed as input +# Returns +# ------- +# Extracted excerpts +# """ +# logging.info("Splitting text into valid excerpts for classification") +# string_list = markdown_utils.remove_bibtex(string_list) +# logging.info("Extracting excerpts for classification") +# divisions = mardown_parser.extract_blocks_excerpts(string_list) +# logging.info("Text Successfully split.") +# output = {} +# for division in divisions: +# original = division +# division = regular_expressions.remove_links_images(division) +# if len(division) > 0: +# output[division] = original +# return output diff --git a/src/somef_core/parser/description_parser 2.py b/src/somef_core/parser/description_parser 2.py new file mode 100644 index 0000000..0da8f8f --- /dev/null +++ b/src/somef_core/parser/description_parser 2.py @@ -0,0 +1,204 @@ +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants + +def parse_description_file(file_path, metadata_result: Result, source): + + """ + Parse a DESCRIPTION file to extract metadata. + + Parameters + ---------- + file_path: path of the DESCRIPTION file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + """ + + try: + if Path(file_path).name.upper() == "DESCRIPTION": + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "DESCRIPTION", + "value": source, + "type": constants.URL, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + + package_match = re.search(r'Package:\s*([^\n]+)', content) + if package_match: + print("FOUND PACKAGE NAME") + package_name = package_match.group(1).strip() + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": package_name, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + print("NO PACKAGE NAME FOUND") + + desc_match = re.search(r'Description:\s*([^\n]+(?:\n\s+[^\n]+)*)', content) + if desc_match: + description = desc_match.group(1).strip() + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(r'Version:\s*([^\n]+)', content) + if version_match: + version = version_match.group(1).strip() + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + authors_section = re.search(r'Authors@R:\s*c\(([\s\S]*?)\)\s*$', content, re.MULTILINE) + # authors_section = re.search(r'Authors@R:\s*c\(([^)]+)\)', content, re.DOTALL) + if authors_section: + authors_text = authors_section.group(1) + + pattern = re.compile( + r'''person\( + \s*"([^"]+)" + (?:\s*,\s*"([^"]*)")? + (?:\s*,\s*)* + (?: + "(?P[^"]+@[^"]+)" + | + .*?email\s*=\s*"(?P[^"]+)" + )? + [^)]* + \)''', + re.VERBOSE + ) + # person_entries = re.findall(r'person\(\s*"([^"]+)"\s*,\s*"([^"]+)"(?:\s*,\s*)?(?:"[^"]*")?(?:\s*,\s*)?(?:"([^"]+)")?', authors_text) + person_entries = [] + for match in pattern.finditer(authors_text): + given = match.group(1) + family = match.group(2) or "" + email = match.group("email1") or match.group("email2") or "" + person_entries.append((given, family, email)) + + for given, family, email in person_entries: + name = given.strip() + if family: + name += " " + family.strip() + author = { + "value": name, + "type": constants.AGENT, + } + + if email: + author["email"] = email.strip() + + metadata_result.add_result( + constants.CAT_AUTHORS, + author, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + license_match = re.search(r'License:\s*([^\n]+)', content) + if license_match: + license_text = license_match.group(1).strip() + metadata_result.add_result( + constants.CAT_LICENSE, + { + "value": license_text, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + url_section = re.search(r'URL:\s*([^\n]+(?:\n\s+[^\n]+)*)', content) + if url_section: + url_text = url_section.group(1).strip() + urls = [] + for url in re.split(r',\s*', url_text): + stripped = url.strip() + if stripped: + urls.append(stripped) + + for url in urls: + if 'github.com' in url.lower() or 'gitlab.com' in url.lower(): + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + issue_tracker_match = re.search(r'BugReports:\s*([^\n]+)', content) + if issue_tracker_match: + issue_tracker_url = issue_tracker_match.group(1).strip() + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": issue_tracker_url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result + + diff --git a/src/somef_core/parser/description_parser.py b/src/somef_core/parser/description_parser.py new file mode 100644 index 0000000..0da8f8f --- /dev/null +++ b/src/somef_core/parser/description_parser.py @@ -0,0 +1,204 @@ +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants + +def parse_description_file(file_path, metadata_result: Result, source): + + """ + Parse a DESCRIPTION file to extract metadata. + + Parameters + ---------- + file_path: path of the DESCRIPTION file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + """ + + try: + if Path(file_path).name.upper() == "DESCRIPTION": + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": "DESCRIPTION", + "value": source, + "type": constants.URL, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "r", encoding="utf-8") as f: + content = f.read() + + package_match = re.search(r'Package:\s*([^\n]+)', content) + if package_match: + print("FOUND PACKAGE NAME") + package_name = package_match.group(1).strip() + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": package_name, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + print("NO PACKAGE NAME FOUND") + + desc_match = re.search(r'Description:\s*([^\n]+(?:\n\s+[^\n]+)*)', content) + if desc_match: + description = desc_match.group(1).strip() + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(r'Version:\s*([^\n]+)', content) + if version_match: + version = version_match.group(1).strip() + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + authors_section = re.search(r'Authors@R:\s*c\(([\s\S]*?)\)\s*$', content, re.MULTILINE) + # authors_section = re.search(r'Authors@R:\s*c\(([^)]+)\)', content, re.DOTALL) + if authors_section: + authors_text = authors_section.group(1) + + pattern = re.compile( + r'''person\( + \s*"([^"]+)" + (?:\s*,\s*"([^"]*)")? + (?:\s*,\s*)* + (?: + "(?P[^"]+@[^"]+)" + | + .*?email\s*=\s*"(?P[^"]+)" + )? + [^)]* + \)''', + re.VERBOSE + ) + # person_entries = re.findall(r'person\(\s*"([^"]+)"\s*,\s*"([^"]+)"(?:\s*,\s*)?(?:"[^"]*")?(?:\s*,\s*)?(?:"([^"]+)")?', authors_text) + person_entries = [] + for match in pattern.finditer(authors_text): + given = match.group(1) + family = match.group(2) or "" + email = match.group("email1") or match.group("email2") or "" + person_entries.append((given, family, email)) + + for given, family, email in person_entries: + name = given.strip() + if family: + name += " " + family.strip() + author = { + "value": name, + "type": constants.AGENT, + } + + if email: + author["email"] = email.strip() + + metadata_result.add_result( + constants.CAT_AUTHORS, + author, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + license_match = re.search(r'License:\s*([^\n]+)', content) + if license_match: + license_text = license_match.group(1).strip() + metadata_result.add_result( + constants.CAT_LICENSE, + { + "value": license_text, + "type": constants.STRING, + "source": source + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + url_section = re.search(r'URL:\s*([^\n]+(?:\n\s+[^\n]+)*)', content) + if url_section: + url_text = url_section.group(1).strip() + urls = [] + for url in re.split(r',\s*', url_text): + stripped = url.strip() + if stripped: + urls.append(stripped) + + for url in urls: + if 'github.com' in url.lower() or 'gitlab.com' in url.lower(): + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + else: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + issue_tracker_match = re.search(r'BugReports:\s*([^\n]+)', content) + if issue_tracker_match: + issue_tracker_url = issue_tracker_match.group(1).strip() + metadata_result.add_result( + constants.CAT_ISSUE_TRACKER, + { + "value": issue_tracker_url, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result + + diff --git a/src/somef_core/parser/dockerfile_parser 2.py b/src/somef_core/parser/dockerfile_parser 2.py new file mode 100644 index 0000000..d47cd44 --- /dev/null +++ b/src/somef_core/parser/dockerfile_parser 2.py @@ -0,0 +1,227 @@ +import logging +import os +import re +from ..utils import constants +from ..process_results import Result + +def parse_dockerfile(file_path, metadata_result: Result, source): + + print(f"Extracting properties from Dockerfile: {file_path}") + + try: + with open(file_path, "rb") as file: + raw_data = file.read() + + content = raw_data.decode("utf-8") + except (OSError, UnicodeDecodeError) as e: + logging.warning(f"Could not process Dockerfile {file_path}: {e}") + return None + + # print(content) + title_match = re.search( + constants.REGEXP_DOCKER_TITLE, + content, + re.IGNORECASE + ) + + if title_match: + title = title_match.group(1).strip() + if title: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": title, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + description_match = re.search( + constants.REGEXP_DOCKER_DESCRIPTION, + content, + re.IGNORECASE + ) + + if description_match: + description = description_match.group(1).strip() + if description: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + licenses_match = re.search(constants.REGEXP_DOCKER_LICENSES, content, re.IGNORECASE) + if licenses_match: + license_info_spdx = detect_license_spdx(licenses_match.group(1).strip()) + + if license_info_spdx: + license_data = { + "value": licenses_match.group(1).strip(), + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": licenses_match.group(1).strip(), + "type": constants.LICENSE + } + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + # source_match = re.search(constants.REGEXP_DOCKER_SOURCE, content, re.IGNORECASE) + # if source_match: + # properties[constants.PROP_SOURCE] = source_match.group(1).strip() + + url_match = re.search(constants.REGEXP_DOCKER_URL, content, re.IGNORECASE) + if url_match: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": url_match.group(1).strip(), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(constants.REGEXP_DOCKER_VERSION, content, re.IGNORECASE) + if version_match: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version_match.group(1).strip(), + "type": constants.RELEASE, + "tag": version_match.group(1).strip() + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + documentation_match = re.search(constants.REGEXP_DOCKER_DOCUMENTATION, content, re.IGNORECASE) + if documentation_match: + metadata_result.add_result( + constants.CAT_DOCUMENTATION, + { + "value": documentation_match.group(1).strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + vendor_match = re.search( + constants.REGEXP_DOCKER_VENDOR, + content, + re.IGNORECASE + ) + + if vendor_match: + vendor = vendor_match.group(1).strip() + if vendor: + if vendor and re.search(constants.REGEXP_LTD_INC, vendor, re.IGNORECASE): + type_vendor = "Organization" + else: + type_vendor = "Person" + + metadata_result.add_result( + constants.CAT_OWNER, + { + "value": vendor, + "type": type_vendor + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # Extract maintainers + maintainers = [] + unique_maintainers = [] + + maintainer_oci_match = re.findall( + constants.REGEXP_MAINTAINER_LABEL_OCI, + content, + re.IGNORECASE | re.MULTILINE + ) + # LABEL maintainer free + maintanainer_label_match = re.findall( + constants.REGEXP_MAINTAINER_LABEL_FREE, + content, + re.IGNORECASE | re.MULTILINE + ) + # Deprecated maintainer + maintainer_match = re.findall( + constants.REGEXP_MAINTAINER, + content, + re.IGNORECASE | re.MULTILINE + ) + maintainers.extend(maintainer_oci_match) + maintainers.extend(maintanainer_label_match) + maintainers.extend(maintainer_match) + + unique_maintainers = list({m.strip() for m in maintainers if m.strip()}) + + for maintainer in unique_maintainers: + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "type": constants.AGENT, + "value": maintainer + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + return metadata_result + +def detect_license_spdx(license_text): + """ + Function that given a license text, infers the name and spdx id in a dockerfile + Parameters + ---------- + license_text + + Returns + ------- + A JSON dictionary with name and spdx id + """ + print("Detecting license from text:", license_text) + for license_name, license_info in constants.LICENSES_DICT.items(): + if re.search(license_info["regex"], license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": f"{license_info['spdx_id']}", + "@id": f"https://spdx.org/licenses/{license_info['spdx_id']}" + } + + for license_name, license_info in constants.LICENSES_DICT.items(): + spdx_id = license_info["spdx_id"] + if re.search(rf'\b{re.escape(spdx_id)}\b', license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": spdx_id, + "@id": f"https://spdx.org/licenses/{spdx_id}" + } + return None + + \ No newline at end of file diff --git a/src/somef_core/parser/dockerfile_parser.py b/src/somef_core/parser/dockerfile_parser.py new file mode 100644 index 0000000..d47cd44 --- /dev/null +++ b/src/somef_core/parser/dockerfile_parser.py @@ -0,0 +1,227 @@ +import logging +import os +import re +from ..utils import constants +from ..process_results import Result + +def parse_dockerfile(file_path, metadata_result: Result, source): + + print(f"Extracting properties from Dockerfile: {file_path}") + + try: + with open(file_path, "rb") as file: + raw_data = file.read() + + content = raw_data.decode("utf-8") + except (OSError, UnicodeDecodeError) as e: + logging.warning(f"Could not process Dockerfile {file_path}: {e}") + return None + + # print(content) + title_match = re.search( + constants.REGEXP_DOCKER_TITLE, + content, + re.IGNORECASE + ) + + if title_match: + title = title_match.group(1).strip() + if title: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": title, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + description_match = re.search( + constants.REGEXP_DOCKER_DESCRIPTION, + content, + re.IGNORECASE + ) + + if description_match: + description = description_match.group(1).strip() + if description: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + licenses_match = re.search(constants.REGEXP_DOCKER_LICENSES, content, re.IGNORECASE) + if licenses_match: + license_info_spdx = detect_license_spdx(licenses_match.group(1).strip()) + + if license_info_spdx: + license_data = { + "value": licenses_match.group(1).strip(), + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": licenses_match.group(1).strip(), + "type": constants.LICENSE + } + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + # source_match = re.search(constants.REGEXP_DOCKER_SOURCE, content, re.IGNORECASE) + # if source_match: + # properties[constants.PROP_SOURCE] = source_match.group(1).strip() + + url_match = re.search(constants.REGEXP_DOCKER_URL, content, re.IGNORECASE) + if url_match: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": url_match.group(1).strip(), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + version_match = re.search(constants.REGEXP_DOCKER_VERSION, content, re.IGNORECASE) + if version_match: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": version_match.group(1).strip(), + "type": constants.RELEASE, + "tag": version_match.group(1).strip() + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + documentation_match = re.search(constants.REGEXP_DOCKER_DOCUMENTATION, content, re.IGNORECASE) + if documentation_match: + metadata_result.add_result( + constants.CAT_DOCUMENTATION, + { + "value": documentation_match.group(1).strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + vendor_match = re.search( + constants.REGEXP_DOCKER_VENDOR, + content, + re.IGNORECASE + ) + + if vendor_match: + vendor = vendor_match.group(1).strip() + if vendor: + if vendor and re.search(constants.REGEXP_LTD_INC, vendor, re.IGNORECASE): + type_vendor = "Organization" + else: + type_vendor = "Person" + + metadata_result.add_result( + constants.CAT_OWNER, + { + "value": vendor, + "type": type_vendor + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # Extract maintainers + maintainers = [] + unique_maintainers = [] + + maintainer_oci_match = re.findall( + constants.REGEXP_MAINTAINER_LABEL_OCI, + content, + re.IGNORECASE | re.MULTILINE + ) + # LABEL maintainer free + maintanainer_label_match = re.findall( + constants.REGEXP_MAINTAINER_LABEL_FREE, + content, + re.IGNORECASE | re.MULTILINE + ) + # Deprecated maintainer + maintainer_match = re.findall( + constants.REGEXP_MAINTAINER, + content, + re.IGNORECASE | re.MULTILINE + ) + maintainers.extend(maintainer_oci_match) + maintainers.extend(maintanainer_label_match) + maintainers.extend(maintainer_match) + + unique_maintainers = list({m.strip() for m in maintainers if m.strip()}) + + for maintainer in unique_maintainers: + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "type": constants.AGENT, + "value": maintainer + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + return metadata_result + +def detect_license_spdx(license_text): + """ + Function that given a license text, infers the name and spdx id in a dockerfile + Parameters + ---------- + license_text + + Returns + ------- + A JSON dictionary with name and spdx id + """ + print("Detecting license from text:", license_text) + for license_name, license_info in constants.LICENSES_DICT.items(): + if re.search(license_info["regex"], license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": f"{license_info['spdx_id']}", + "@id": f"https://spdx.org/licenses/{license_info['spdx_id']}" + } + + for license_name, license_info in constants.LICENSES_DICT.items(): + spdx_id = license_info["spdx_id"] + if re.search(rf'\b{re.escape(spdx_id)}\b', license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": spdx_id, + "@id": f"https://spdx.org/licenses/{spdx_id}" + } + return None + + \ No newline at end of file diff --git a/src/somef_core/parser/gemspec_parser 2.py b/src/somef_core/parser/gemspec_parser 2.py new file mode 100644 index 0000000..6714b01 --- /dev/null +++ b/src/somef_core/parser/gemspec_parser 2.py @@ -0,0 +1,222 @@ +import os +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_gemspec_file(file_path, metadata_result: Result, source): + # To do Version + # To do Email + """ + Parse a Ruby gemspec file to extract metadata. + + Parameters + ---------- + file_path: path of the gemspec file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + metadata_result: Updated metadata result object + """ + try: + if file_path.endswith('.gemspec'): + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": Path(file_path).name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + name_match = re.search(r'gem\.name\s*=\s*["\']([^"\']+)["\']', content) + if name_match: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + desc_match = re.search(r'gem\.description\s*=\s*%q{([^}]+)}|gem\.description\s*=\s*["\']([^"\']+)["\']', content) + if desc_match: + description = desc_match.group(1) if desc_match.group(1) else desc_match.group(2) + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + homepage_match = re.search(r'gem\.homepage\s*=\s*["\']([^"\']+)["\']', content) + if homepage_match: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": homepage_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + authors_match = re.findall(r'gem\.author[s]?\s*=\s*(?P"[^"]*"|\[[^\]]*\])', content) + + for match in authors_match: + if match.startswith('['): + author_list = re.findall(r'["\']([^"\']+)["\']', match) + else: + author_list = [re.sub(r'["\']', '', match).strip()] + + for author in author_list: + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "type": constants.AGENT, + "value": author + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # authors_str = authors_match.group(1) + # author_list = re.findall(r'["\']([^"\']+)["\']', authors_str) + + # for author in author_list: + # metadata_result.add_result( + # constants.CAT_AUTHORS, + # { + # "type": constants.AGENT, + # "value": author + # }, + # 1, + # constants.TECHNIQUE_CODE_CONFIG_PARSER, + # source + # ) + + # license_match = re.search(r'gem\.license\s*=\s*["\']([^"\']+)["\']', content) + license_match = re.search(r'gem\.license[s]?\s*=\s*["\']([^"\']+)["\']', content) + if license_match: + license_value = license_match.group(1) + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'Ruby') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + dependency_matches = re.search(r'gem\.requirements\s*=\s*(\[.*?\])', content, re.DOTALL) + + if dependency_matches: + array_requirements = dependency_matches.group(1) + dependencies = re.findall(r'["\']([^"\']+)["\']', array_requirements) + + if dependencies: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": dependencies, + "type": constants.SOFTWARE_APPLICATION, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + dependency_matches = re.findall(r'gem\.add_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?', content) + for dep in dependency_matches: + name = dep[0] + version = dep[1] if len(dep) > 1 and dep[1] else "any" + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dev_dependency_matches = re.findall(r'gem\.add_development_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?', content) + for dep in dev_dependency_matches: + name = dep[0] + version = dep[1] if len(dep) > 1 and dep[1] else "any" + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "dev" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/gemspec_parser.py b/src/somef_core/parser/gemspec_parser.py new file mode 100644 index 0000000..6714b01 --- /dev/null +++ b/src/somef_core/parser/gemspec_parser.py @@ -0,0 +1,222 @@ +import os +import re +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx + +def parse_gemspec_file(file_path, metadata_result: Result, source): + # To do Version + # To do Email + """ + Parse a Ruby gemspec file to extract metadata. + + Parameters + ---------- + file_path: path of the gemspec file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + ------- + metadata_result: Updated metadata result object + """ + try: + if file_path.endswith('.gemspec'): + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": Path(file_path).name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + name_match = re.search(r'gem\.name\s*=\s*["\']([^"\']+)["\']', content) + if name_match: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_match.group(1), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + desc_match = re.search(r'gem\.description\s*=\s*%q{([^}]+)}|gem\.description\s*=\s*["\']([^"\']+)["\']', content) + if desc_match: + description = desc_match.group(1) if desc_match.group(1) else desc_match.group(2) + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + homepage_match = re.search(r'gem\.homepage\s*=\s*["\']([^"\']+)["\']', content) + if homepage_match: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": homepage_match.group(1), + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + authors_match = re.findall(r'gem\.author[s]?\s*=\s*(?P"[^"]*"|\[[^\]]*\])', content) + + for match in authors_match: + if match.startswith('['): + author_list = re.findall(r'["\']([^"\']+)["\']', match) + else: + author_list = [re.sub(r'["\']', '', match).strip()] + + for author in author_list: + metadata_result.add_result( + constants.CAT_AUTHORS, + { + "type": constants.AGENT, + "value": author + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # authors_str = authors_match.group(1) + # author_list = re.findall(r'["\']([^"\']+)["\']', authors_str) + + # for author in author_list: + # metadata_result.add_result( + # constants.CAT_AUTHORS, + # { + # "type": constants.AGENT, + # "value": author + # }, + # 1, + # constants.TECHNIQUE_CODE_CONFIG_PARSER, + # source + # ) + + # license_match = re.search(r'gem\.license\s*=\s*["\']([^"\']+)["\']', content) + license_match = re.search(r'gem\.license[s]?\s*=\s*["\']([^"\']+)["\']', content) + if license_match: + license_value = license_match.group(1) + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'Ruby') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + dependency_matches = re.search(r'gem\.requirements\s*=\s*(\[.*?\])', content, re.DOTALL) + + if dependency_matches: + array_requirements = dependency_matches.group(1) + dependencies = re.findall(r'["\']([^"\']+)["\']', array_requirements) + + if dependencies: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": dependencies, + "type": constants.SOFTWARE_APPLICATION, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + dependency_matches = re.findall(r'gem\.add_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?', content) + for dep in dependency_matches: + name = dep[0] + version = dep[1] if len(dep) > 1 and dep[1] else "any" + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dev_dependency_matches = re.findall(r'gem\.add_development_dependency\s*["\']([^"\']+)["\'](?:\s*,\s*["\']([^"\']+)["\'])?', content) + for dep in dev_dependency_matches: + name = dep[0] + version = dep[1] if len(dep) > 1 and dep[1] else "any" + req = f"{name}: {version}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "dev" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + except Exception as e: + logging.error(f"Error parsing gemspec file from {file_path}: {str(e)}") + + return metadata_result \ No newline at end of file diff --git a/src/somef_core/parser/package_json_parser.py b/src/somef_core/parser/package_json_parser.py index 83ba1eb..a0884c5 100644 --- a/src/somef_core/parser/package_json_parser.py +++ b/src/somef_core/parser/package_json_parser.py @@ -46,7 +46,18 @@ def parse_package_json_file(file_path, metadata_result: Result, source): constants.TECHNIQUE_CODE_CONFIG_PARSER, source ) - + + if "homepage" in data: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": data["homepage"], + "type": constants.URL}, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if "version" in data: metadata_result.add_result( constants.CAT_VERSION, @@ -137,7 +148,24 @@ def parse_package_json_file(file_path, metadata_result: Result, source): constants.TECHNIQUE_CODE_CONFIG_PARSER, source ) - + + runtimes = parse_runtime_platform_from_package_json(data) + if runtimes: + for runtime in runtimes: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + runtime, + # { + # "value": runtime["version"], + # "version": runtime["version"], + # "name": runtime["name"], + # "type": constants.STRING + # }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + deps = {} deps.update(data.get("dependencies", {})) deps.update(data.get("devDependencies", {})) @@ -160,7 +188,8 @@ def parse_package_json_file(file_path, metadata_result: Result, source): metadata_result.add_result( constants.CAT_HAS_PACKAGE_FILE, { - "value": "package.json", + # "value": "package.json", + "value": source, "type": constants.URL, }, 1, @@ -199,4 +228,40 @@ def parse_bugs(bugs_data): return bugs_data["url"] if isinstance(bugs_data, str): return bugs_data - return None \ No newline at end of file + return None + +def parse_runtime_platform_from_package_json(data): + """ + Extract runtime information from a package.json dict. + Returns a list of dicts with 'name' and 'version', e.g.: + [{'name': 'Node.js', 'version': '18.x'}] + """ + runtimes = [] + + engines = data.get("engines", {}) + if isinstance(engines, dict): + for runtime_name, version_value in engines.items(): + + if version_value: + value_str = f"{runtime_name}: {version_value}".strip() + else: + value_str = runtime_name + + run = { + "value": value_str, + "name": runtime_name.capitalize(), + "type": constants.STRING + } + if version_value: + run["version"] = version_value.strip() + + # if version_value: + # # runtimes.append({ + # # "name": runtime_name.capitalize(), + # # "version": version_value.strip() + # # }) + # run["version"]= version_value.strip() + + runtimes.append(run) + + return runtimes \ No newline at end of file diff --git a/src/somef_core/parser/pom_xml_parser.py b/src/somef_core/parser/pom_xml_parser.py index b9a799e..dfb9c1c 100644 --- a/src/somef_core/parser/pom_xml_parser.py +++ b/src/somef_core/parser/pom_xml_parser.py @@ -40,6 +40,7 @@ def parse_pom_file(file_path, metadata_result: Result, source): data = lxml.etree.parse(file) root = data.getroot() + if root.tag != "{" + POM_NAMESPACE + "}project": logging.warning(f"Expected root tag 'project' in {POM_NAMESPACE} namespace, got {root.tag} instead") return metadata_result @@ -59,7 +60,9 @@ def parse_pom_file(file_path, metadata_result: Result, source): "dependencies": [], "developers": [], "issue_tracker": None, - "scm_url": None + "scm_url": None, + "homepage": [], + "runtime_platform": [] } for key, node in parse_node(root): @@ -81,9 +84,17 @@ def parse_pom_file(file_path, metadata_result: Result, source): project_data["scm_url"] = parse_scm(node) elif key == "developers": project_data["developers"] = parse_developers(node) + # elif key == "dependencies" or key == "dependencyManagement": + # project_data["dependencies"] = parse_dependencies(node) elif key == "dependencies": - project_data["dependencies"] = parse_dependencies(node) - + project_data["dependencies"].extend(parse_dependencies(node)) + elif key == "dependencyManagement": + for k, n in parse_node(node): + if k == "dependencies": + project_data["dependencies"].extend(parse_dependencies(n)) + elif key == "properties": + project_data["runtime_platform"] = parse_runtime_platform(node) + if group_id or artifact_id: identifier_value = f"{group_id or ''}.{artifact_id or ''}".strip(':') metadata_result.add_result( @@ -120,7 +131,18 @@ def parse_pom_file(file_path, metadata_result: Result, source): constants.TECHNIQUE_CODE_CONFIG_PARSER, source ) - + + if project_data["homepage"]: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": project_data["homepage"], + "type": constants.URL}, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + if project_data["scm_url"]: metadata_result.add_result( constants.CAT_PACKAGE_DISTRIBUTION, @@ -132,7 +154,7 @@ def parse_pom_file(file_path, metadata_result: Result, source): constants.TECHNIQUE_CODE_CONFIG_PARSER, source ) - + if project_data["dependencies"]: for dependency in project_data["dependencies"]: metadata_result.add_result( @@ -148,29 +170,60 @@ def parse_pom_file(file_path, metadata_result: Result, source): source ) - if project_data["developers"] : - metadata_result.add_result( - constants.CAT_AUTHORS , - { - "value": project_data["developers"], - "type": constants.URL - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) + + if project_data["developers"]: + for author in project_data["developers"]: + + if "type" not in author: + author["type"] = constants.AGENT + + metadata_result.add_result( + constants.CAT_AUTHORS, + author, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) if repositories: - metadata_result.add_result( - constants.CAT_PACKAGE_DISTRIBUTION, - { - "value": repositories, - "type": constants.URL - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) + + for rep in repositories: + rep["type"] = constants.URL + + metadata_result.add_result( + constants.CAT_PACKAGE_DISTRIBUTION, + rep, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # constants.CAT_PACKAGE_DISTRIBUTION, + # { + # # "value": repositories, + # rep, + # "type": constants.URL + # }, + # 1, + # constants.TECHNIQUE_CODE_CONFIG_PARSER, + # source + # ) + + if project_data["runtime_platform"]: + + for runtime in project_data["runtime_platform"]: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": runtime["value"], + "version": runtime["version"], + "name": runtime["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) metadata = {} for k, v in project_data.items(): @@ -180,7 +233,8 @@ def parse_pom_file(file_path, metadata_result: Result, source): metadata_result.add_result( constants.CAT_HAS_PACKAGE_FILE, { - "value": "pom.xml", + # "value": "pom.xml", + "value": source, "type": constants.URL }, 1, @@ -189,7 +243,6 @@ def parse_pom_file(file_path, metadata_result: Result, source): ) processed_pom = True - return metadata_result def parse_licenses(licenses_node): @@ -204,16 +257,27 @@ def parse_licenses(licenses_node): licenses.append(license_data) return licenses -def parse_dependencies(dependencies_node): +def parse_dependencies(node): dependencies = [] - for key, node in parse_node(dependencies_node): - if key == "dependency": + + for child in node: + if not isinstance(child.tag, str): + continue + + tag = child.tag.split("}")[-1] + if tag == "dependencies": + dependencies.extend(parse_dependencies(child)) + elif tag == "dependency": dep_data = {} - for key2, node2 in parse_node(node): - if key2 in ["groupId", "artifactId", "version"] and node2.text: - dep_data[key2] = node2.text + for sub in child: + if not isinstance(sub.tag, str): + continue + sub_tag = sub.tag.split("}")[-1] + if sub_tag in ["groupId", "artifactId", "version"] and sub.text: + dep_data[sub_tag] = sub.text.strip() if dep_data: dependencies.append(dep_data) + return dependencies def parse_developers(developers_node): @@ -222,10 +286,10 @@ def parse_developers(developers_node): if key == "developer": dev_data = {} author_data = { - "name": None, - "email": None, - "url": None, - "organization": None, + # "name": None, + # "email": None, + # "url": None, + # "affiliation": None, "type": constants.AGENT } for key2, node2 in parse_node(node): @@ -237,10 +301,10 @@ def parse_developers(developers_node): elif key2 == "url" and node2.text: author_data["url"] = node2.text elif key2 == "organization" and node2.text: - author_data["organization"] = node2.text + author_data["affiliation"] = node2.text - if not author_data["value"]: - author_data["value"] = author_data["email"] or author_data["organization"] + if "value" not in author_data: + author_data["value"] = author_data["email"] or author_data["affiliation"] dev_data.update({k: v for k, v in author_data.items() if k != "type"}) developers.append(dev_data) return developers @@ -264,7 +328,65 @@ def parse_repositories(repo_node): repo_data = {} for key2, node2 in parse_node(node): if key2 in ["id", "name", "url"] and node2.text: - repo_data[key2] = node2.text + if key2 == "id": + repo_data["value"] = node2.text + else: + repo_data[key2] = node2.text if repo_data: repos.append(repo_data) - return repos \ No newline at end of file + return repos + +def parse_runtime_platform(properties_node): + """ + Extracts runtime platform information from a node in a pom.xml. + Returns a list of dictionaries with runtime names and versions, or an empty list if none are found. + + Parameters + ---------- + properties_node : lxml.etree.Element + The node from the POM file. + + Returns + ------- + list of dict + Each dict has the keys 'name' and 'version', e.g. [{'name': 'Java', 'version': '1.8'}, {'name': 'Python', 'version': '3.11'}]. + Returns an empty list if no runtime information is present. + """ + runtimes = [] + + if properties_node is None: + return runtimes + + for child in properties_node: + if not isinstance(child.tag, str): + continue + tag = child.tag.split("}")[-1].lower() + text = (child.text or "").strip() + + if not text: + continue + # if tag.startswith(f"{{{POM_NAMESPACE}}}") and tag.endswith(".version") and child.text: + # print('entramos') + # runtime_name = tag.split("}")[-1].split(".")[0].capitalize() + # version_value = child.text.strip() + # runtimes.append({"value": f'{runtime_name} {version_value}',"name": runtime_name, "version": version_value}) + if any(x in tag for x in ["java.version", "javaversion", "java_version"]): + runtimes.append({ + "name": "Java", + "version": text, + "value": f"Java: {text}" + }) + elif any(x in tag for x in ["kotlin.version", "kotlinversion", "kotlin_version"]): + runtimes.append({ + "name": "Kotlin", + "version": text, + "value": f"Kotlin: {text}" + }) + elif any(x in tag for x in ["scala.version", "scalaversion", "scala_version"]): + runtimes.append({ + "name": "Scala", + "version": text, + "value": f"Scala: {text}" + }) + + return runtimes \ No newline at end of file diff --git a/src/somef_core/parser/publiccode_parser 2.py b/src/somef_core/parser/publiccode_parser 2.py new file mode 100644 index 0000000..d51651b --- /dev/null +++ b/src/somef_core/parser/publiccode_parser 2.py @@ -0,0 +1,384 @@ + +import json +import yaml +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +import re + +def parse_publiccode_file(file_path, metadata_result: Result, source): + """ + Parse a publiccode.yml file and extract relevant metadata. + + Parameters + ---------- + file_path: path of the publiccode.yml file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + """ + print("file_path publiccode:", file_path) + try: + with open(file_path, 'r', encoding='utf-8') as file: + content = yaml.safe_load(file) + + except Exception as e: + logging.warning(f"Could not parse publiccode.yml {file_path}: {e}") + return metadata_result + + if not isinstance(content, dict): + return metadata_result + + if Path(file_path).name.lower() in {"publiccode.yml", "publiccode.yaml"}: + print("Detected publiccode.yml file.") + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "url" in content: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": content["url"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + #application domain: Categories and description.[lang].genericName + if "categories" in content: + for category in content["categories"]: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": category, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "name" in content: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": content["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in content: + # this is the structure. But we don't need the language + # description: + # en: + # genericName: Registry + # es: + # genericName: Registro + description = content.get("description", {}) + + generic_names = { + lang_block["genericName"] + for lang_block in description.values() + if isinstance(lang_block, dict) and "genericName" in lang_block + } + for generic_name in generic_names: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": generic_name, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + short_descriptions = [ + lang_block.get("shortDescription") + for lang_block in description.values() + if isinstance(lang_block, dict) + ] + for short_desc in filter(None, short_descriptions): + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": short_desc.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + long_descriptions = [ + lang_block.get("longDescription") + for lang_block in description.values() + if isinstance(lang_block, dict) + ] + for long_desc in filter(None, long_descriptions): + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": long_desc.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + names = { + lang_block.get("localisedName") + for lang_block in description.values() + if isinstance(lang_block, dict) + } + for name in filter(None, names): + metadata_result.add_result( + constants.CAT_NAME, + { + "value": name.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + keywords = [] + for lang_block in description.values(): + if not isinstance(lang_block, dict): + continue + + features = lang_block.get("features", []) + if isinstance(features, list): + for feature in features: + if isinstance(feature, str): + keywords.append(feature) + + if keywords: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keywords, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "platforms" in content: + for platform in content["platforms"]: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": platform, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + depends_on = content.get("dependsOn", {}) +# dependsOn: +# open: or propietary or hardware +# - name: MySQL +# versionMin: "1.1" +# versionMax: "1.3" +# optional: true + for dep_type, dep_list in depends_on.items(): # dep_type = "open", "proprietary", "hardware" + for dep in dep_list: + name = dep.get("name") + version = None + version_str = None + + # complex version handling because sometimes is version and sometimes versionMin/versionMax + if "version" in dep: + version = dep["version"] + version_str = f"=={version}" + else: + version_min = dep.get("versionMin") + version_max = dep.get("versionMax") + if version_min and version_max: + version = f">={version_min},<{version_max}" + version_str = version + elif version_min: + version = f">={version_min}" + version_str = version + elif version_max: + version = f"<{version_max}" + version_str = version + + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": f"{name}{version_str}" if version_str else name, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareVersion" in content: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": content["softwareVersion"], + "type": constants.RELEASE, + "tag": content["softwareVersion"] + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "developmentStatus" in content: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": content["developmentStatus"], + "type": constants.RELEASE, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "legal" in content: + legal = content["legal"] + if "license" in legal: + license_info_spdx = detect_license_spdx(legal["license"]) + + if license_info_spdx: + license_data = { + "value": legal["license"], + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": legal["license"], + "type": constants.LICENSE + } + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "releaseDate" in content: + date_published = content["releaseDate"] + # Add both date published and date updated with the same value + if date_published: + metadata_result.add_result( + constants.CAT_DATE_PUBLISHED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + metadata_result.add_result( + constants.CAT_DATE_UPDATED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "maintenance" in content: + maintenance = content.get("maintenance", {}) + # maintenance_type = maintenance.get("type") + + # if maintenance_type == "contract": + role_map = [ + ("contractors", "maintenance_contractor"), + ("contacts", "maintenance_contact"), + ] + + for key, role in role_map: + for person in maintenance.get(key, []): + author_data = { + "type": constants.AGENT, + "value": person.get("name", ""), + "name": person.get("name", ""), + "role": role + } + + if "email" in person: + author_data["email"] = person["email"] + + if "website" in person: + author_data["url"] = person["website"] + + if "affiliation" in person: + author_data["affiliation"] = person["affiliation"] + + metadata_result.add_result( + constants.CAT_OWNER, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + return metadata_result + + +def detect_license_spdx(license_text): + """ + Function that given a license text, infers the name and spdx id in a dockerfile + Parameters + ---------- + license_text + + Returns + ------- + A JSON dictionary with name and spdx id + """ + + for license_name, license_info in constants.LICENSES_DICT.items(): + if re.search(license_info["regex"], license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": f"{license_info['spdx_id']}", + "@id": f"https://spdx.org/licenses/{license_info['spdx_id']}" + } + + for license_name, license_info in constants.LICENSES_DICT.items(): + spdx_id = license_info["spdx_id"] + if re.search(rf'\b{re.escape(spdx_id)}\b', license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": spdx_id, + "@id": f"https://spdx.org/licenses/{spdx_id}" + } + return None diff --git a/src/somef_core/parser/publiccode_parser.py b/src/somef_core/parser/publiccode_parser.py new file mode 100644 index 0000000..d51651b --- /dev/null +++ b/src/somef_core/parser/publiccode_parser.py @@ -0,0 +1,384 @@ + +import json +import yaml +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +import re + +def parse_publiccode_file(file_path, metadata_result: Result, source): + """ + Parse a publiccode.yml file and extract relevant metadata. + + Parameters + ---------- + file_path: path of the publiccode.yml file being analysed + metadata_result: metadata object where the metadata dictionary is kept + source: source of the package file (URL) + + Returns + """ + print("file_path publiccode:", file_path) + try: + with open(file_path, 'r', encoding='utf-8') as file: + content = yaml.safe_load(file) + + except Exception as e: + logging.warning(f"Could not parse publiccode.yml {file_path}: {e}") + return metadata_result + + if not isinstance(content, dict): + return metadata_result + + if Path(file_path).name.lower() in {"publiccode.yml", "publiccode.yaml"}: + print("Detected publiccode.yml file.") + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "url" in content: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": content["url"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + #application domain: Categories and description.[lang].genericName + if "categories" in content: + for category in content["categories"]: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": category, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "name" in content: + metadata_result.add_result( + constants.CAT_NAME, + { + "value": content["name"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "description" in content: + # this is the structure. But we don't need the language + # description: + # en: + # genericName: Registry + # es: + # genericName: Registro + description = content.get("description", {}) + + generic_names = { + lang_block["genericName"] + for lang_block in description.values() + if isinstance(lang_block, dict) and "genericName" in lang_block + } + for generic_name in generic_names: + metadata_result.add_result( + constants.CAT_APPLICATION_DOMAIN, + { + "value": generic_name, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + short_descriptions = [ + lang_block.get("shortDescription") + for lang_block in description.values() + if isinstance(lang_block, dict) + ] + for short_desc in filter(None, short_descriptions): + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": short_desc.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + long_descriptions = [ + lang_block.get("longDescription") + for lang_block in description.values() + if isinstance(lang_block, dict) + ] + for long_desc in filter(None, long_descriptions): + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": long_desc.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + names = { + lang_block.get("localisedName") + for lang_block in description.values() + if isinstance(lang_block, dict) + } + for name in filter(None, names): + metadata_result.add_result( + constants.CAT_NAME, + { + "value": name.strip(), + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + keywords = [] + for lang_block in description.values(): + if not isinstance(lang_block, dict): + continue + + features = lang_block.get("features", []) + if isinstance(features, list): + for feature in features: + if isinstance(feature, str): + keywords.append(feature) + + if keywords: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keywords, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "platforms" in content: + for platform in content["platforms"]: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": platform, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + depends_on = content.get("dependsOn", {}) +# dependsOn: +# open: or propietary or hardware +# - name: MySQL +# versionMin: "1.1" +# versionMax: "1.3" +# optional: true + for dep_type, dep_list in depends_on.items(): # dep_type = "open", "proprietary", "hardware" + for dep in dep_list: + name = dep.get("name") + version = None + version_str = None + + # complex version handling because sometimes is version and sometimes versionMin/versionMax + if "version" in dep: + version = dep["version"] + version_str = f"=={version}" + else: + version_min = dep.get("versionMin") + version_max = dep.get("versionMax") + if version_min and version_max: + version = f">={version_min},<{version_max}" + version_str = version + elif version_min: + version = f">={version_min}" + version_str = version + elif version_max: + version = f"<{version_max}" + version_str = version + + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": f"{name}{version_str}" if version_str else name, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": "runtime" + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "softwareVersion" in content: + metadata_result.add_result( + constants.CAT_VERSION, + { + "value": content["softwareVersion"], + "type": constants.RELEASE, + "tag": content["softwareVersion"] + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "developmentStatus" in content: + metadata_result.add_result( + constants.CAT_DEV_STATUS, + { + "value": content["developmentStatus"], + "type": constants.RELEASE, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "legal" in content: + legal = content["legal"] + if "license" in legal: + license_info_spdx = detect_license_spdx(legal["license"]) + + if license_info_spdx: + license_data = { + "value": legal["license"], + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": legal["license"], + "type": constants.LICENSE + } + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "releaseDate" in content: + date_published = content["releaseDate"] + # Add both date published and date updated with the same value + if date_published: + metadata_result.add_result( + constants.CAT_DATE_PUBLISHED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + metadata_result.add_result( + constants.CAT_DATE_UPDATED, + { + "value": date_published, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "maintenance" in content: + maintenance = content.get("maintenance", {}) + # maintenance_type = maintenance.get("type") + + # if maintenance_type == "contract": + role_map = [ + ("contractors", "maintenance_contractor"), + ("contacts", "maintenance_contact"), + ] + + for key, role in role_map: + for person in maintenance.get(key, []): + author_data = { + "type": constants.AGENT, + "value": person.get("name", ""), + "name": person.get("name", ""), + "role": role + } + + if "email" in person: + author_data["email"] = person["email"] + + if "website" in person: + author_data["url"] = person["website"] + + if "affiliation" in person: + author_data["affiliation"] = person["affiliation"] + + metadata_result.add_result( + constants.CAT_OWNER, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + return metadata_result + + +def detect_license_spdx(license_text): + """ + Function that given a license text, infers the name and spdx id in a dockerfile + Parameters + ---------- + license_text + + Returns + ------- + A JSON dictionary with name and spdx id + """ + + for license_name, license_info in constants.LICENSES_DICT.items(): + if re.search(license_info["regex"], license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": f"{license_info['spdx_id']}", + "@id": f"https://spdx.org/licenses/{license_info['spdx_id']}" + } + + for license_name, license_info in constants.LICENSES_DICT.items(): + spdx_id = license_info["spdx_id"] + if re.search(rf'\b{re.escape(spdx_id)}\b', license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": spdx_id, + "@id": f"https://spdx.org/licenses/{spdx_id}" + } + return None diff --git a/src/somef_core/parser/python_parser.py b/src/somef_core/parser/python_parser.py index f0f02e1..63a3f3a 100644 --- a/src/somef_core/parser/python_parser.py +++ b/src/somef_core/parser/python_parser.py @@ -13,17 +13,20 @@ """ def parse_dependency(dependency_str): + if not dependency_str: return None, None - parts = re.split(r'(>=|<=|==|!=|>|<|~=|\[)', dependency_str, 1) + # parts = re.split(r'(>=|<=|==|!=|>|<|~=|\[)', dependency_str, 1) + parts = re.split(r'(>=|<=|==|!=|>|<|~=)', dependency_str, 1) name = parts[0].strip() if len(parts) > 1: version = ''.join(parts[1:]) else: version = "" - version = version.strip("[]() -.,:") - + # version = version.strip("[]() -.,:") + version = re.sub(r'[\[\]\(\)]', '', version) + return name, version def parse_url_type(url_label): @@ -39,6 +42,8 @@ def parse_url_type(url_label): return constants.CAT_README_URL elif "download" in label: return constants.CAT_DOWNLOAD_URL + elif "homepage" in label: + return constants.CAT_HOMEPAGE else: return constants.CAT_RELATED_DOCUMENTATION @@ -60,246 +65,6 @@ def get_project_data(data): project = data["tool"]["poetry"] return project -def parse_pyproject_toml(file_path, metadata_result: Result, source): - """ - - Parameters - ---------- - file_path: path to the package file being analysed - metadata_result: Metadata object dictionary - source: source of the package file (URL) - - Returns - ------- - - """ - try: - if Path(file_path).name == "pyproject.toml": - metadata_result.add_result( - constants.CAT_HAS_PACKAGE_FILE, - { - "value": "pyproject.toml", - "type": constants.URL, - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - with open(file_path, "rb") as f: - data = tomli.load(f) - - project = get_project_data(data) - - if "name" in project: - metadata_result.add_result( - constants.CAT_PACKAGE_ID, - { - "value": project["name"], - "type": constants.STRING - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - if "description" in project: - metadata_result.add_result( - constants.CAT_DESCRIPTION, - { - "value": project["description"], - "type": constants.STRING - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - if "version" in project: - metadata_result.add_result( - constants.CAT_VERSION, - { - "value": project["version"], - "type": constants.RELEASE, - "tag": project["version"] - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - dependencies = project.get("dependencies", []) - if isinstance(dependencies, list): - for req in dependencies: - name, version = parse_dependency(req) - if name: - metadata_result.add_result( - constants.CAT_REQUIREMENTS, - { - "value": req, - "name": name, - "version": version, - "type": constants.SOFTWARE_APPLICATION - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - elif isinstance(dependencies, dict): - for name, version in dependencies.items(): - req = f"{name}{version}" if version else name - metadata_result.add_result( - constants.CAT_REQUIREMENTS, - { - "value": req, - "name": name, - "version": version, - "type": constants.SOFTWARE_APPLICATION - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - # This is for detecting the "requires" section in a pyrpoject.toml file - if "build-system" in data and "requires" in data["build-system"]: - build_requires = data["build-system"]["requires"] - if isinstance(build_requires, list): - for req in build_requires: - name, version = parse_dependency(req) - if name: - metadata_result.add_result( - constants.CAT_REQUIREMENTS, - { - "value": req, - "name": name, - "version": version, - "type": constants.SOFTWARE_APPLICATION - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - urls = project.get("urls", {}) - if not urls and "tool" in data and "poetry" in data["tool"]: - - poetry = data["tool"]["poetry"] - if "repository" in poetry: - urls["repository"] = poetry["repository"] - if "homepage" in poetry: - urls["homepage"] = poetry["homepage"] - if "documentation" in poetry: - urls["documentation"] = poetry["documentation"] - - for url_type, url in urls.items(): - category = parse_url_type(url_type) - metadata_result.add_result( - category, - { - "value": url, - "type": constants.URL - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - authors = project.get("authors", []) - if isinstance(authors, list): - for author in authors: - if isinstance(author, dict): - author_data = { - "name": author.get("name"), - "email": author.get("email"), - "type": constants.AGENT, - "value": author.get("name") - } - if author.get("url") is not None: - author_data["url"] = author.get("url") - else: - - parsed = parse_author_string(author) - author_data = { - "name": parsed["name"], - "email": parsed["email"], - "type": constants.AGENT, - "value": parsed["name"] - } - - metadata_result.add_result( - constants.CAT_AUTHORS, - author_data, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - if "license" in project: - license_info = project["license"] - license_text = "" - - if isinstance(license_info, dict): - # Check if license is specified as a file - license_path_file = license_info["file"] - dir_path_license = os.path.dirname(file_path) - license_path = os.path.join(dir_path_license, license_path_file) - - if os.path.exists(license_path): - with open(license_path, "r", encoding="utf-8") as f: - license_text = f.read() - - if "file" in license_info: - license_value = f"License file: {license_info['file']}" - else: - license_text = license_info.get("text", "") - license_value = license_info.get("type", "") - else: - license_text = "" - license_value = license_info - - license_info_spdx = detect_license_spdx(license_text, 'JSON') - spdx_id = "" - spdx_name = "" - - if license_info_spdx: - license_data = { - "value": license_value, - "spdx_id": license_info_spdx.get('spdx_id'), - "name": license_info_spdx.get('name'), - "type": constants.LICENSE - } - else: - license_data = { - "value": license_value, - "type": constants.LICENSE - } - - metadata_result.add_result( - constants.CAT_LICENSE, - license_data, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - if "keywords" in project: - for keyword in project["keywords"]: - metadata_result.add_result( - constants.CAT_KEYWORDS, - { - "value": keyword, - "type": constants.STRING - }, - 1, - constants.TECHNIQUE_CODE_CONFIG_PARSER, - source - ) - - except Exception as e: - logging.error(f"Error parsing pyproject.toml from {file_path}: {str(e)}") - - return metadata_result - def parse_requirements_txt(file_path, metadata_result: Result, source): """ Parameters @@ -314,22 +79,43 @@ def parse_requirements_txt(file_path, metadata_result: Result, source): """ try: if Path(file_path).name.lower() in ["requirements.txt", "requirement.txt"]: - - + with open(file_path, "r", encoding="utf-8") as f: - for line in f: + lines = f.readlines() + + for line in lines: line = line.strip() if not line or line.startswith('#'): continue name, version = parse_dependency(line) if name: - metadata_result.add_result( - constants.CAT_REQUIREMENTS, - { + req = { "value": line, "name": name, - "version": version, "type": constants.SOFTWARE_APPLICATION + } + if version: + req['version'] = version + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + req, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + + runtimes = parse_runtime_platform_from_requirements(lines) + if runtimes: + for runtime in runtimes: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": runtime["value"], + "version": runtime["version"], + "name": runtime["name"], + "type": constants.STRING }, 1, constants.TECHNIQUE_CODE_CONFIG_PARSER, @@ -404,7 +190,7 @@ def parse_setup_py(file_path, metadata_result: Result, source): constants.CAT_AUTHORS, { "name": value, - "email": None, + # "email": None, "type": constants.AGENT, }, 1, @@ -420,8 +206,12 @@ def parse_setup_py(file_path, metadata_result: Result, source): value = module_vars[keyword.value.id] else: value = ast.literal_eval(keyword.value) - - author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + + # author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + author_results = [ + a for a in metadata_result.results.get(constants.CAT_AUTHORS, []) + if a.get("technique") == constants.TECHNIQUE_CODE_CONFIG_PARSER + ] if author_results: for result in author_results: result["result"]["email"] = value @@ -429,7 +219,7 @@ def parse_setup_py(file_path, metadata_result: Result, source): metadata_result.add_result( constants.CAT_AUTHORS, { - "name": None, + # "name": None, "email": value, "type": constants.AGENT, "value": value @@ -564,4 +354,72 @@ def parse_setup_py(file_path, metadata_result: Result, source): except Exception as e: logging.error(f"Error parsing setup.py from {file_path}: {str(e)}") - return metadata_result \ No newline at end of file + return metadata_result + +def parse_runtime_platform_from_pyproject(project_section): + """ + Given the `[tool.poetry]` section from pyproject.toml, + this method extracts the runtime platform(s) declared (e.g. Python version). Return a list of dicts. + + """ + runtimes = [] + + deps = project_section.get("dependencies", {}) + if isinstance(deps, dict): + python_spec = deps.get("python") + if python_spec: + runtimes.append({"name": "Python", "version": python_spec, "value": f'Python {python_spec}'}) + + req_python = project_section.get("requires-python") + if req_python: + runtimes.append({"name": "Python", "version": req_python, "value": f'Python {python_spec}'}) + + return runtimes + +def parse_runtime_platform_from_requirements(requirements_lines): + """ + Extracts runtime information (e.g., Python) from a requirements.txt file. + Only returns an entry if the runtime is explicitly mentioned with a version. + + Parameters + ---------- + requirements_lines : + Lines from the requirements.txt file. + + Returns + ------- + list of dict + Each dictionary has the keys 'name' and 'version', e.g.: + [{'name': 'Python', 'version': '3.11'}] + Returns an empty list if no explicit runtime information is found. + """ + runtimes = [] + + if not requirements_lines: + return runtimes + + for line in requirements_lines: + clean_line = line.strip() + if not clean_line or clean_line.startswith('#'): + continue + + if clean_line.lower().startswith('python'): + version = None + + for sep in ['==', '>=', '<=', '~=', '>', '<']: + if sep in clean_line: + version = clean_line.split(sep)[1].strip() + break + + if version is None: + match = re.search(r'python\s*([0-9.]+)', clean_line, re.IGNORECASE) + if not match: + match = re.search(r'python([0-9.]+)', clean_line, re.IGNORECASE) + if match: + version = match.group(1) + + if version: + runtimes.append({'name': 'Python', 'version': version, 'value': f'Python: {version}'}) + break + + return runtimes \ No newline at end of file diff --git a/src/somef_core/parser/toml_parser 2.py b/src/somef_core/parser/toml_parser 2.py new file mode 100644 index 0000000..fb33080 --- /dev/null +++ b/src/somef_core/parser/toml_parser 2.py @@ -0,0 +1,675 @@ +# -*- coding: utf-8 -*- +import tomli +import re +import os +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx, detect_spdx_from_declared + + +def parse_toml_file(file_path, metadata_result: Result, source): + """ + Unified TOML parser that handles Cargo.toml, pyproject.toml, and Project.toml files. + + Parameters + ---------- + file_path: path to the TOML file being analyzed + metadata_result: Metadata object dictionary + source: source of the package file (URL) + + Returns + ------- + metadata_result: Updated metadata result object + """ + try: + filename = Path(file_path).name.lower() + + if filename == "cargo.toml": + file_type = "cargo" + display_name = "Cargo.toml" + + elif filename == "pyproject.toml": + file_type = "pyproject" + display_name = "pyproject.toml" + + elif filename == "project.toml": + file_type = "julia_project" + display_name = "Project.toml" + + else: + logging.warning(f"Unknown TOML file type: {filename}") + return metadata_result + + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": display_name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "rb") as f: + data = tomli.load(f) + + if file_type == "cargo": + parse_cargo_metadata(data, metadata_result, source, file_path) + elif file_type == "pyproject": + parse_pyproject_metadata(data, metadata_result, source, file_path) + elif file_type == "julia_project": + parse_julia_project_metadata(data, metadata_result, source) + + except Exception as e: + logging.error(f"Error parsing TOML file {file_path}: {str(e)}") + + return metadata_result + + +def extract_common_name_field(data, metadata_result, source, file_type): + """ + Extract 'name' field that's common across Cargo.toml, pyproject.toml, and Project.toml. + + For Cargo.toml: data["package"]["name"] + For pyproject.toml: data["project"]["name"] or data["tool"]["poetry"]["name"] + For Project.toml: data["name"] + """ + name_value = None + + if file_type == "cargo" and "package" in data and "name" in data["package"]: + name_value = data["package"]["name"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "name" in project: + name_value = project["name"] + + elif file_type == "julia_project" and "name" in data: + name_value = data["name"] + + if name_value: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_value, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_version_field(data, metadata_result, source, file_type): + """ + Extract 'version' field that's common across all three TOML types. + + For Cargo.toml: data["package"]["version"] + For pyproject.toml: data["project"]["version"] or data["tool"]["poetry"]["version"] + For Project.toml: data["version"] + """ + version_value = None + + if file_type == "cargo" and "package" in data and "version" in data["package"]: + version_value = data["package"]["version"] + version_type = constants.RELEASE + + elif file_type == "pyproject": + project = get_project_data(data) + if "version" in project: + version_value = project["version"] + version_type = constants.RELEASE + + elif file_type == "julia_project" and "version" in data: + version_value = data["version"] + version_type = constants.STRING + + if version_value: + result_dict = { + "value": version_value, + "type": version_type + } + if file_type in ["cargo", "pyproject"]: + result_dict["tag"] = version_value + + metadata_result.add_result( + constants.CAT_VERSION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_description_field(data, metadata_result, source, file_type): + """ + Extract 'description' field common to Cargo.toml and pyproject.toml. + + For Cargo.toml: data["package"]["description"] + For pyproject.toml: data["project"]["description"] or data["tool"]["poetry"]["description"] + """ + description_value = None + + if file_type == "cargo" and "package" in data and "description" in data["package"]: + description_value = data["package"]["description"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "description" in project: + description_value = project["description"] + + if description_value: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description_value, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_authors_field(data, metadata_result, source, file_type): + """ + Extract 'authors' field common across all three TOML types. + + All three formats can have authors with name and email. + """ + authors = None + + if file_type == "cargo" and "package" in data and "authors" in data["package"]: + authors = data["package"]["authors"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "authors" in project: + authors = project["authors"] + + elif file_type == "julia_project" and "authors" in data: + authors = data["authors"] + + if authors: + for author in authors: + if isinstance(author, dict): + # pyproject.toml format: {name: "...", email: "..."} + author_data = { + "name": author.get("name"), + "email": author.get("email"), + "type": constants.AGENT, + "value": author.get("name") + } + if author.get("url"): + author_data["url"] = author.get("url") + else: + # String format "Name " or just "Name" + match = re.match(r'^(.+?)\s*<(.+?)>$', str(author).strip()) + if match: + author_name = match.group(1).strip() + author_email = match.group(2).strip() + author_data = { + "name": author_name, + "email": author_email, + "type": constants.AGENT, + "value": author_name + } + else: + author_data = { + "name": str(author).strip(), + "email": None, + "type": constants.AGENT, + "value": str(author).strip() + } + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_keywords_field(data, metadata_result, source, file_type): + """ + Extract 'keywords' field common to Cargo.toml and pyproject.toml. + """ + keywords = None + + if file_type == "cargo" and "package" in data and "keywords" in data["package"]: + keywords = data["package"]["keywords"] + elif file_type == "pyproject": + project = get_project_data(data) + if "keywords" in project: + keywords = project["keywords"] + + if keywords: + for keyword in keywords: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_cargo_metadata(data, metadata_result, source, file_path): + """Parse Cargo.toml specific metadata.""" + + extract_common_name_field(data, metadata_result, source, "cargo") + extract_common_version_field(data, metadata_result, source, "cargo") + extract_common_description_field(data, metadata_result, source, "cargo") + extract_common_authors_field(data, metadata_result, source, "cargo") + extract_common_keywords_field(data, metadata_result, source, "cargo") + + if "package" in data and "repository" in data["package"]: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": data["package"]["repository"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "package" in data and "license" in data["package"]: + license_value = data["package"]["license"] + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'JSON') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dependencies" in data: + dependencies = data["dependencies"] + for name, info in dependencies.items(): + version, dep_type, req_details = determine_dependency_type(info) + req = f"{name} = {{ {req_details} }}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # target-specific dependencies + for key in data: + if key.startswith("target.") and isinstance(data[key], dict) and "dependencies" in data[key]: + target_deps = data[key]["dependencies"] + for name, info in target_deps.items(): + version, dep_type, req_details = determine_dependency_type(info) + req = f"{name} = {{ {req_details} }} (target-specific)" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_pyproject_metadata(data, metadata_result, source, file_path): + """Parse pyproject.toml specific metadata.""" + project = get_project_data(data) + + extract_common_name_field(data, metadata_result, source, "pyproject") + extract_common_version_field(data, metadata_result, source, "pyproject") + extract_common_description_field(data, metadata_result, source, "pyproject") + extract_common_authors_field(data, metadata_result, source, "pyproject") + extract_common_keywords_field(data, metadata_result, source, "pyproject") + + if "homepage" in project: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": project["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dependencies = project.get("dependencies", []) + if isinstance(dependencies, list): + for req in dependencies: + name, version = parse_dependency(req) + if name: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(dependencies, dict): + for name, version in dependencies.items(): + req = f"{name}{version}" if version else name + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # build-system requires + if "build-system" in data and "requires" in data["build-system"]: + build_requires = data["build-system"]["requires"] + if isinstance(build_requires, list): + for req in build_requires: + name, version = parse_dependency(req) + if name: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + urls = project.get("urls", {}) + + if not urls and "tool" in data and "poetry" in data["tool"]: + poetry = data["tool"]["poetry"] + if "repository" in poetry: + urls["repository"] = poetry["repository"] + if "homepage" in poetry: + urls["homepage"] = poetry["homepage"] + if "documentation" in poetry: + urls["documentation"] = poetry["documentation"] + + for url_type, url in urls.items(): + category = parse_url_type(url_type) + metadata_result.add_result( + category, + { + "value": url, + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in project: + license_info = project["license"] + license_text = "" + + if isinstance(license_info, dict): + license_path_file = license_info.get("file") + if license_path_file: + dir_path_license = os.path.dirname(file_path) + license_path = os.path.join(dir_path_license, license_path_file) + + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as f: + license_text = f.read() + + license_value = f"License file: {license_path_file}" + else: + license_text = license_info.get("text", "") + license_value = license_info.get("type", "") + else: + license_text = "" + license_value = license_info + + + licence_info_spdx = None + + if license_text: + license_info_spdx = detect_license_spdx(license_text, 'JSON') + else: + # there is no text in licence and we cant detect license in the text as usual, + # so we check if the declared license matches an SPDX ID from our dictionary of licences + license_info_spdx = detect_spdx_from_declared(license_value) + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + runtimes = parse_runtime_platform_from_pyproject(project) + if runtimes: + for runtime in runtimes: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": f'{runtime["name"]}{runtime["version"]}', + "name": runtime["name"], + "version": runtime["version"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_julia_project_metadata(data, metadata_result, source): + """Parse Project.toml (Julia) specific metadata.""" + extract_common_name_field(data, metadata_result, source, "julia_project") + extract_common_version_field(data, metadata_result, source, "julia_project") + extract_common_authors_field(data, metadata_result, source, "julia_project") + + if "uuid" in data: + metadata_result.add_result( + constants.CAT_IDENTIFIER, + { + "value": data["uuid"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "deps" in data: + deps = data["deps"] + for req in deps.keys(): + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "compat" in data: + compat = data["compat"] + for package_name, version in compat.items(): + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": f"{package_name}", + "package": package_name, + "version": version, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +# Helper functions + +def get_project_data(data): + """Get project section from pyproject.toml (handles both standard and Poetry formats).""" + project = data.get("project", {}) + if not project and "tool" in data and "poetry" in data["tool"]: + project = data["tool"]["poetry"] + return project + + +def parse_dependency(dependency_str): + """Parse a dependency string to extract name and version.""" + if not dependency_str: + return None, None + + parts = re.split(r'(>=|<=|==|!=|>|<|~=)', dependency_str, 1) + name = parts[0].strip() + if len(parts) > 1: + version = ''.join(parts[1:]) + else: + version = "" + + version = re.sub(r'[\[\]]', '', version) + + return name, version + + +def parse_url_type(url_label): + """Determine the category for a URL based on its label.""" + label = url_label.lower() + + if "repository" in label or label in ("git", "github", "code", "sourcecode", "source"): + return constants.CAT_CODE_REPOSITORY + elif "issue" in label or label in ("bug tracker", "tracker", "issues"): + return constants.CAT_ISSUE_TRACKER + elif "doc" in label or label in ("documentation", "api reference", "reference"): + return constants.CAT_DOCUMENTATION + elif label == "readme": + return constants.CAT_README_URL + elif "download" in label: + return constants.CAT_DOWNLOAD_URL + elif "homepage" in label: + return constants.CAT_HOMEPAGE + else: + return constants.CAT_RELATED_DOCUMENTATION + + +def determine_dependency_type(info): + """Determine the type of dependency for Cargo.toml.""" + if isinstance(info, dict): + if "version" in info: + version = info["version"] + req = f"version = {version}" + dep_type = "version" + elif "git" in info: + version = info["git"] + req = f"git = \"{version}\"" + dep_type = "url" + elif "path" in info: + version = info["path"] + req = f"path = \"{version}\"" + dep_type = "path" + else: + version = str(info) + req = f"other = {version}" + dep_type = "other" + else: + version = info + req = f"version = {version}" + dep_type = "version" + + return version, dep_type, req + + +def parse_runtime_platform_from_pyproject(project_section): + """Extract runtime platform from pyproject.toml.""" + runtimes = [] + + deps = project_section.get("dependencies", {}) + if isinstance(deps, dict): + python_spec = deps.get("python") + if python_spec: + runtimes.append({"name": "Python", "version": python_spec}) + + req_python = project_section.get("requires-python") + if req_python: + runtimes.append({"name": "Python", "version": req_python}) + + return runtimes diff --git a/src/somef_core/parser/toml_parser.py b/src/somef_core/parser/toml_parser.py new file mode 100644 index 0000000..fb33080 --- /dev/null +++ b/src/somef_core/parser/toml_parser.py @@ -0,0 +1,675 @@ +# -*- coding: utf-8 -*- +import tomli +import re +import os +import logging +from pathlib import Path +from ..process_results import Result +from ..utils import constants +from ..regular_expressions import detect_license_spdx, detect_spdx_from_declared + + +def parse_toml_file(file_path, metadata_result: Result, source): + """ + Unified TOML parser that handles Cargo.toml, pyproject.toml, and Project.toml files. + + Parameters + ---------- + file_path: path to the TOML file being analyzed + metadata_result: Metadata object dictionary + source: source of the package file (URL) + + Returns + ------- + metadata_result: Updated metadata result object + """ + try: + filename = Path(file_path).name.lower() + + if filename == "cargo.toml": + file_type = "cargo" + display_name = "Cargo.toml" + + elif filename == "pyproject.toml": + file_type = "pyproject" + display_name = "pyproject.toml" + + elif filename == "project.toml": + file_type = "julia_project" + display_name = "Project.toml" + + else: + logging.warning(f"Unknown TOML file type: {filename}") + return metadata_result + + metadata_result.add_result( + constants.CAT_HAS_PACKAGE_FILE, + { + # "value": display_name, + "value": source, + "type": constants.URL, + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + with open(file_path, "rb") as f: + data = tomli.load(f) + + if file_type == "cargo": + parse_cargo_metadata(data, metadata_result, source, file_path) + elif file_type == "pyproject": + parse_pyproject_metadata(data, metadata_result, source, file_path) + elif file_type == "julia_project": + parse_julia_project_metadata(data, metadata_result, source) + + except Exception as e: + logging.error(f"Error parsing TOML file {file_path}: {str(e)}") + + return metadata_result + + +def extract_common_name_field(data, metadata_result, source, file_type): + """ + Extract 'name' field that's common across Cargo.toml, pyproject.toml, and Project.toml. + + For Cargo.toml: data["package"]["name"] + For pyproject.toml: data["project"]["name"] or data["tool"]["poetry"]["name"] + For Project.toml: data["name"] + """ + name_value = None + + if file_type == "cargo" and "package" in data and "name" in data["package"]: + name_value = data["package"]["name"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "name" in project: + name_value = project["name"] + + elif file_type == "julia_project" and "name" in data: + name_value = data["name"] + + if name_value: + metadata_result.add_result( + constants.CAT_PACKAGE_ID, + { + "value": name_value, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_version_field(data, metadata_result, source, file_type): + """ + Extract 'version' field that's common across all three TOML types. + + For Cargo.toml: data["package"]["version"] + For pyproject.toml: data["project"]["version"] or data["tool"]["poetry"]["version"] + For Project.toml: data["version"] + """ + version_value = None + + if file_type == "cargo" and "package" in data and "version" in data["package"]: + version_value = data["package"]["version"] + version_type = constants.RELEASE + + elif file_type == "pyproject": + project = get_project_data(data) + if "version" in project: + version_value = project["version"] + version_type = constants.RELEASE + + elif file_type == "julia_project" and "version" in data: + version_value = data["version"] + version_type = constants.STRING + + if version_value: + result_dict = { + "value": version_value, + "type": version_type + } + if file_type in ["cargo", "pyproject"]: + result_dict["tag"] = version_value + + metadata_result.add_result( + constants.CAT_VERSION, + result_dict, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_description_field(data, metadata_result, source, file_type): + """ + Extract 'description' field common to Cargo.toml and pyproject.toml. + + For Cargo.toml: data["package"]["description"] + For pyproject.toml: data["project"]["description"] or data["tool"]["poetry"]["description"] + """ + description_value = None + + if file_type == "cargo" and "package" in data and "description" in data["package"]: + description_value = data["package"]["description"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "description" in project: + description_value = project["description"] + + if description_value: + metadata_result.add_result( + constants.CAT_DESCRIPTION, + { + "value": description_value, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_authors_field(data, metadata_result, source, file_type): + """ + Extract 'authors' field common across all three TOML types. + + All three formats can have authors with name and email. + """ + authors = None + + if file_type == "cargo" and "package" in data and "authors" in data["package"]: + authors = data["package"]["authors"] + + elif file_type == "pyproject": + project = get_project_data(data) + if "authors" in project: + authors = project["authors"] + + elif file_type == "julia_project" and "authors" in data: + authors = data["authors"] + + if authors: + for author in authors: + if isinstance(author, dict): + # pyproject.toml format: {name: "...", email: "..."} + author_data = { + "name": author.get("name"), + "email": author.get("email"), + "type": constants.AGENT, + "value": author.get("name") + } + if author.get("url"): + author_data["url"] = author.get("url") + else: + # String format "Name " or just "Name" + match = re.match(r'^(.+?)\s*<(.+?)>$', str(author).strip()) + if match: + author_name = match.group(1).strip() + author_email = match.group(2).strip() + author_data = { + "name": author_name, + "email": author_email, + "type": constants.AGENT, + "value": author_name + } + else: + author_data = { + "name": str(author).strip(), + "email": None, + "type": constants.AGENT, + "value": str(author).strip() + } + + metadata_result.add_result( + constants.CAT_AUTHORS, + author_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def extract_common_keywords_field(data, metadata_result, source, file_type): + """ + Extract 'keywords' field common to Cargo.toml and pyproject.toml. + """ + keywords = None + + if file_type == "cargo" and "package" in data and "keywords" in data["package"]: + keywords = data["package"]["keywords"] + elif file_type == "pyproject": + project = get_project_data(data) + if "keywords" in project: + keywords = project["keywords"] + + if keywords: + for keyword in keywords: + metadata_result.add_result( + constants.CAT_KEYWORDS, + { + "value": keyword, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_cargo_metadata(data, metadata_result, source, file_path): + """Parse Cargo.toml specific metadata.""" + + extract_common_name_field(data, metadata_result, source, "cargo") + extract_common_version_field(data, metadata_result, source, "cargo") + extract_common_description_field(data, metadata_result, source, "cargo") + extract_common_authors_field(data, metadata_result, source, "cargo") + extract_common_keywords_field(data, metadata_result, source, "cargo") + + if "package" in data and "repository" in data["package"]: + metadata_result.add_result( + constants.CAT_CODE_REPOSITORY, + { + "value": data["package"]["repository"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "package" in data and "license" in data["package"]: + license_value = data["package"]["license"] + license_text = "" + + dir_path = os.path.dirname(file_path) + license_paths = [ + os.path.join(dir_path, "LICENSE"), + os.path.join(dir_path, "LICENSE.txt"), + os.path.join(dir_path, "LICENSE.md") + ] + + for license_path in license_paths: + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as lf: + license_text = lf.read() + break + + license_info_spdx = detect_license_spdx(license_text, 'JSON') + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "dependencies" in data: + dependencies = data["dependencies"] + for name, info in dependencies.items(): + version, dep_type, req_details = determine_dependency_type(info) + req = f"{name} = {{ {req_details} }}" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # target-specific dependencies + for key in data: + if key.startswith("target.") and isinstance(data[key], dict) and "dependencies" in data[key]: + target_deps = data[key]["dependencies"] + for name, info in target_deps.items(): + version, dep_type, req_details = determine_dependency_type(info) + req = f"{name} = {{ {req_details} }} (target-specific)" + + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION, + "dependency_type": dep_type + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_pyproject_metadata(data, metadata_result, source, file_path): + """Parse pyproject.toml specific metadata.""" + project = get_project_data(data) + + extract_common_name_field(data, metadata_result, source, "pyproject") + extract_common_version_field(data, metadata_result, source, "pyproject") + extract_common_description_field(data, metadata_result, source, "pyproject") + extract_common_authors_field(data, metadata_result, source, "pyproject") + extract_common_keywords_field(data, metadata_result, source, "pyproject") + + if "homepage" in project: + metadata_result.add_result( + constants.CAT_HOMEPAGE, + { + "value": project["homepage"], + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + dependencies = project.get("dependencies", []) + if isinstance(dependencies, list): + for req in dependencies: + name, version = parse_dependency(req) + if name: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + elif isinstance(dependencies, dict): + for name, version in dependencies.items(): + req = f"{name}{version}" if version else name + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + # build-system requires + if "build-system" in data and "requires" in data["build-system"]: + build_requires = data["build-system"]["requires"] + if isinstance(build_requires, list): + for req in build_requires: + name, version = parse_dependency(req) + if name: + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "name": name, + "version": version, + "type": constants.SOFTWARE_APPLICATION + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + urls = project.get("urls", {}) + + if not urls and "tool" in data and "poetry" in data["tool"]: + poetry = data["tool"]["poetry"] + if "repository" in poetry: + urls["repository"] = poetry["repository"] + if "homepage" in poetry: + urls["homepage"] = poetry["homepage"] + if "documentation" in poetry: + urls["documentation"] = poetry["documentation"] + + for url_type, url in urls.items(): + category = parse_url_type(url_type) + metadata_result.add_result( + category, + { + "value": url, + "type": constants.URL + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "license" in project: + license_info = project["license"] + license_text = "" + + if isinstance(license_info, dict): + license_path_file = license_info.get("file") + if license_path_file: + dir_path_license = os.path.dirname(file_path) + license_path = os.path.join(dir_path_license, license_path_file) + + if os.path.exists(license_path): + with open(license_path, "r", encoding="utf-8") as f: + license_text = f.read() + + license_value = f"License file: {license_path_file}" + else: + license_text = license_info.get("text", "") + license_value = license_info.get("type", "") + else: + license_text = "" + license_value = license_info + + + licence_info_spdx = None + + if license_text: + license_info_spdx = detect_license_spdx(license_text, 'JSON') + else: + # there is no text in licence and we cant detect license in the text as usual, + # so we check if the declared license matches an SPDX ID from our dictionary of licences + license_info_spdx = detect_spdx_from_declared(license_value) + + if license_info_spdx: + license_data = { + "value": license_value, + "spdx_id": license_info_spdx.get('spdx_id'), + "name": license_info_spdx.get('name'), + "type": constants.LICENSE + } + else: + license_data = { + "value": license_value, + "type": constants.LICENSE + } + + metadata_result.add_result( + constants.CAT_LICENSE, + license_data, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + runtimes = parse_runtime_platform_from_pyproject(project) + if runtimes: + for runtime in runtimes: + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": f'{runtime["name"]}{runtime["version"]}', + "name": runtime["name"], + "version": runtime["version"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +def parse_julia_project_metadata(data, metadata_result, source): + """Parse Project.toml (Julia) specific metadata.""" + extract_common_name_field(data, metadata_result, source, "julia_project") + extract_common_version_field(data, metadata_result, source, "julia_project") + extract_common_authors_field(data, metadata_result, source, "julia_project") + + if "uuid" in data: + metadata_result.add_result( + constants.CAT_IDENTIFIER, + { + "value": data["uuid"], + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "deps" in data: + deps = data["deps"] + for req in deps.keys(): + metadata_result.add_result( + constants.CAT_REQUIREMENTS, + { + "value": req, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + if "compat" in data: + compat = data["compat"] + for package_name, version in compat.items(): + metadata_result.add_result( + constants.CAT_RUNTIME_PLATFORM, + { + "value": f"{package_name}", + "package": package_name, + "version": version, + "type": constants.STRING + }, + 1, + constants.TECHNIQUE_CODE_CONFIG_PARSER, + source + ) + + +# Helper functions + +def get_project_data(data): + """Get project section from pyproject.toml (handles both standard and Poetry formats).""" + project = data.get("project", {}) + if not project and "tool" in data and "poetry" in data["tool"]: + project = data["tool"]["poetry"] + return project + + +def parse_dependency(dependency_str): + """Parse a dependency string to extract name and version.""" + if not dependency_str: + return None, None + + parts = re.split(r'(>=|<=|==|!=|>|<|~=)', dependency_str, 1) + name = parts[0].strip() + if len(parts) > 1: + version = ''.join(parts[1:]) + else: + version = "" + + version = re.sub(r'[\[\]]', '', version) + + return name, version + + +def parse_url_type(url_label): + """Determine the category for a URL based on its label.""" + label = url_label.lower() + + if "repository" in label or label in ("git", "github", "code", "sourcecode", "source"): + return constants.CAT_CODE_REPOSITORY + elif "issue" in label or label in ("bug tracker", "tracker", "issues"): + return constants.CAT_ISSUE_TRACKER + elif "doc" in label or label in ("documentation", "api reference", "reference"): + return constants.CAT_DOCUMENTATION + elif label == "readme": + return constants.CAT_README_URL + elif "download" in label: + return constants.CAT_DOWNLOAD_URL + elif "homepage" in label: + return constants.CAT_HOMEPAGE + else: + return constants.CAT_RELATED_DOCUMENTATION + + +def determine_dependency_type(info): + """Determine the type of dependency for Cargo.toml.""" + if isinstance(info, dict): + if "version" in info: + version = info["version"] + req = f"version = {version}" + dep_type = "version" + elif "git" in info: + version = info["git"] + req = f"git = \"{version}\"" + dep_type = "url" + elif "path" in info: + version = info["path"] + req = f"path = \"{version}\"" + dep_type = "path" + else: + version = str(info) + req = f"other = {version}" + dep_type = "other" + else: + version = info + req = f"version = {version}" + dep_type = "version" + + return version, dep_type, req + + +def parse_runtime_platform_from_pyproject(project_section): + """Extract runtime platform from pyproject.toml.""" + runtimes = [] + + deps = project_section.get("dependencies", {}) + if isinstance(deps, dict): + python_spec = deps.get("python") + if python_spec: + runtimes.append({"name": "Python", "version": python_spec}) + + req_python = project_section.get("requires-python") + if req_python: + runtimes.append({"name": "Python", "version": req_python}) + + return runtimes diff --git a/src/somef_core/process_files.py b/src/somef_core/process_files.py index 548bb39..95ad611 100644 --- a/src/somef_core/process_files.py +++ b/src/somef_core/process_files.py @@ -3,18 +3,30 @@ import re import urllib import yaml +import string from urllib.parse import urlparse -from .utils import constants, markdown_utils +from .utils import constants +# from . import extract_workflows, extract_ontologies from . import extract_workflows from .process_results import Result from .regular_expressions import detect_license_spdx, extract_scholarly_article_natural, extract_scholarly_article_properties from .parser.pom_xml_parser import parse_pom_file from .parser.package_json_parser import parse_package_json_file -from .parser.python_parser import parse_pyproject_toml from .parser.python_parser import parse_setup_py -from.parser.python_parser import parse_requirements_txt +from .parser.codemeta_parser import parse_codemeta_json_file +from .parser.composer_parser import parse_composer_json +from .parser.python_parser import parse_requirements_txt +from .parser.authors_parser import parse_author_file +from .parser.bower_parser import parse_bower_json_file +from .parser.gemspec_parser import parse_gemspec_file +from .parser.description_parser import parse_description_file +from .parser.toml_parser import parse_toml_file +from .parser.cabal_parser import parse_cabal_file +from .parser.dockerfile_parser import parse_dockerfile +from .parser.publiccode_parser import parse_publiccode_file from chardet import detect + domain_gitlab = '' def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner="", repo_name="", @@ -41,12 +53,20 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner domain_gitlab = extract_gitlab_domain(metadata_result, repo_type) text = "" + readmeMD_proccesed = False + try: + parsed_build_files = set() + for dir_path, dir_names, filenames in os.walk(repo_dir): + + dir_names[:] = [d for d in dir_names if d.lower() not in constants.IGNORED_DIRS] repo_relative_path = os.path.relpath(dir_path, repo_dir) + current_dir = os.path.basename(repo_relative_path).lower() # if this is a test folder, we ignore it (except for the root repo) - if ignore_test_folder and repo_relative_path != "." and "test" in repo_relative_path.lower(): - # skip this file if it's in a test folder, or inside one + # if ignore_test_folder and repo_relative_path != "." and "test" in repo_relative_path.lower(): + if ignore_test_folder and repo_relative_path != "." and current_dir in constants.IGNORED_DIRS: + # skip this file if it's in a test folder, ignored dire, or inside one continue for filename in filenames: file_path = os.path.join(repo_relative_path, filename) @@ -58,18 +78,31 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner if filename == "Dockerfile" or filename.lower() == "docker-compose.yml": docker_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, repo_dir, repo_relative_path, filename) + + # full_path = os.path.join(repo_dir, file_path) + + result_value = { + constants.PROP_VALUE: docker_url, + constants.PROP_TYPE: constants.URL, + } + if filename == "Dockerfile": format_file = constants.FORMAT_DOCKERFILE + result_value[constants.PROP_FORMAT] = format_file + metadata_result = parse_dockerfile(os.path.join(dir_path, filename), metadata_result, docker_url) else: format_file = constants.FORMAT_DOCKER_COMPOSE - metadata_result.add_result(constants.CAT_HAS_BUILD_FILE, - { - constants.PROP_VALUE: docker_url, - constants.PROP_TYPE: constants.URL, - constants.PROP_FORMAT: format_file - }, - 1, - constants.TECHNIQUE_FILE_EXPLORATION, docker_url) + + result_value[constants.PROP_FORMAT] = format_file + + metadata_result.add_result( + constants.CAT_HAS_BUILD_FILE, + result_value, + 1, + constants.TECHNIQUE_FILE_EXPLORATION, + docker_url + ) + if filename.lower().endswith(".ipynb"): notebook_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, repo_dir, repo_relative_path, filename) @@ -84,29 +117,51 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner filename_no_ext = os.path.splitext(filename)[0] # this will take into account README, README.MD, README.TXT, README.RST if "README" == filename_no_ext.upper(): - if repo_relative_path == ".": - try: - with open(os.path.join(dir_path, filename), "rb") as data_file: - data_file_text = data_file.read() - try: - text = data_file_text.decode("utf-8") - except UnicodeError as err: - logging.error(f"{type(err).__name__} was raised: {err} Trying other encodings...") - text = data_file_text.decode(detect(data_file_text)["encoding"]) - if repo_type == constants.RepositoryType.GITHUB: - readme_url = convert_to_raw_user_content_github(filename, owner, - repo_name, - repo_default_branch) - metadata_result.add_result(constants.CAT_README_URL, - { - constants.PROP_VALUE: readme_url, - constants.PROP_TYPE: constants.URL - }, - 1, - constants.TECHNIQUE_FILE_EXPLORATION) - except ValueError: - logging.error("README Error: error while reading file content") - logging.error(f"{type(err).__name__} was raised: {err}") + # There is unexpected behavior when the README is available in multiple formats. + # We prioritize the .md format as it is more readable than pdf and others + if not readmeMD_proccesed: + if repo_relative_path == ".": + try: + + with open(os.path.join(dir_path, filename), "rb") as data_file: + data_file_text = data_file.read() + + try: + text = data_file_text.decode("utf-8") + except UnicodeError as err: + logging.error(f"{type(err).__name__} was raised: {err} Trying other encodings...") + # text = data_file_text.decode(detect(data_file_text)["encoding"]) + result_detect = detect(data_file_text) + encoding = result_detect.get("encoding") + if encoding: + try: + text = data_file_text.decode(encoding) + except UnicodeError as err: + logging.warning(f"Detected encoding '{encoding}' failed: {err}. Using utf-8 with replacement.") + text = data_file_text.decode("utf-8", errors="replace") + else: + logging.warning("Could not detect encoding. Using utf-8 with replacement.") + text = data_file_text.decode("utf-8", errors="replace") + text = clean_text(text) + + if repo_type == constants.RepositoryType.GITHUB: + readme_url = convert_to_raw_user_content_github(filename, owner, + repo_name, + repo_default_branch) + metadata_result.add_result(constants.CAT_README_URL, + { + constants.PROP_VALUE: readme_url, + constants.PROP_TYPE: constants.URL + }, + 1, + constants.TECHNIQUE_FILE_EXPLORATION) + + if filename.upper() == "README.MD": + readmeMD_proccesed = True + + except ValueError: + logging.error("README Error: error while reading file content") + logging.error(f"{type(err).__name__} was raised: {err}") if ("LICENCE" == filename.upper() or "LICENSE" == filename.upper() or "LICENSE.MD"== filename.upper() or "LICENSE.RST"== filename.upper()): metadata_result = get_file_content_or_link(repo_type, file_path, owner, repo_name, @@ -133,7 +188,13 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner metadata_result = get_file_content_or_link(repo_type, file_path, owner, repo_name, repo_default_branch, repo_dir, repo_relative_path, filename, dir_path, - metadata_result, constants.CAT_CONTRIBUTORS) + metadata_result, constants.CAT_CONTRIBUTORS) + if "AUTHORS" == filename.upper() or "AUTHORS.MD" == filename.upper() or "AUTHORS.TXT" == filename.upper(): + metadata_result = get_file_content_or_link(repo_type, file_path, owner, repo_name, + repo_default_branch, + repo_dir, repo_relative_path, filename, dir_path, + metadata_result, constants.CAT_AUTHORS) + if "INSTALL" in filename.upper() and filename.upper().endswith("MD"): metadata_result = get_file_content_or_link(repo_type, file_path, owner, repo_name, repo_default_branch, @@ -162,15 +223,33 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner constants.PROP_TYPE: constants.URL }, 1, constants.TECHNIQUE_FILE_EXPLORATION ) + if filename.upper() == constants.CODEOWNERS_FILE: codeowners_json = parse_codeowners_structured(dir_path,filename) + if filename.lower() == "codemeta.json": + if filename.lower() in parsed_build_files and repo_relative_path != ".": + logging.info(f"Ignoring secondary {filename} in {dir_path}") + continue + + codemeta_file_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, repo_dir, repo_relative_path, filename) + metadata_result = parse_codemeta_json_file(os.path.join(dir_path, filename), metadata_result, codemeta_file_url) + parsed_build_files.add(filename.lower()) # TO DO: Code owners not fully implemented yet + if filename.lower() == "pom.xml" or filename.lower() == "package.json" or \ - filename.lower() == "pyproject.toml" or filename.lower() == "setup.py" or filename.lower() == "requirements.txt": + filename.lower() == "pyproject.toml" or filename.lower() == "setup.py" or filename.endswith(".gemspec") or \ + filename.lower() == "requirements.txt" or filename.lower() == "bower.json" or filename == "DESCRIPTION" or \ + (filename.lower() == "cargo.toml" and repo_relative_path == ".") or (filename.lower() == "composer.json" and repo_relative_path == ".") or \ + (filename == "Project.toml" or (filename.lower()== "publiccode.yml" or filename.lower()== "publiccode.yaml") and repo_relative_path == "."): + if filename.lower() in parsed_build_files and repo_relative_path != ".": + logging.info(f"Ignoring secondary {filename} in {dir_path}") + continue + build_file_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, repo_dir, repo_relative_path, filename) + metadata_result.add_result(constants.CAT_HAS_BUILD_FILE, { constants.PROP_VALUE: build_file_url, @@ -179,18 +258,31 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner }, 1, constants.TECHNIQUE_FILE_EXPLORATION, build_file_url) - logging.info(f"############### Processing package file: {filename} ############### ") + logging.info(f"############### (NEW UPDATE) Processing package file: {filename} ############### ") if filename.lower() == "pom.xml": metadata_result = parse_pom_file(os.path.join(dir_path, filename), metadata_result, build_file_url) if filename.lower() == "package.json": metadata_result = parse_package_json_file(os.path.join(dir_path, filename), metadata_result, build_file_url) - if filename.lower() == "pyproject.toml": - metadata_result = parse_pyproject_toml(os.path.join(dir_path, filename), metadata_result, build_file_url) if filename.lower() == "setup.py": metadata_result = parse_setup_py(os.path.join(dir_path, filename), metadata_result, build_file_url) if filename.lower() == "requirements.txt": metadata_result = parse_requirements_txt(os.path.join(dir_path, filename), metadata_result, build_file_url) - + if filename.lower() == "bower.json": + metadata_result = parse_bower_json_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename.lower() == "composer.json": + metadata_result = parse_composer_json(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename.endswith(".gemspec"): + metadata_result = parse_gemspec_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename == "DESCRIPTION": + metadata_result = parse_description_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename.lower() == "pyproject.toml" or filename.lower() == "cargo.toml" or filename == "Project.toml": + metadata_result = parse_toml_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename.endswith == ".cabal": + metadata_result = parse_cabal_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + if filename.lower() == "publiccode.yml" or filename.lower() == "publiccode.yaml": + metadata_result = parse_publiccode_file(os.path.join(dir_path, filename), metadata_result, build_file_url) + parsed_build_files.add(filename.lower()) + # if repo_type == constants.RepositoryType.GITLAB: if filename.endswith(".yml"): if repo_type == constants.RepositoryType.GITLAB: @@ -202,7 +294,15 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner { constants.PROP_VALUE: workflow_url_gitlab, constants.PROP_TYPE: constants.URL - }, 1, constants.TECHNIQUE_FILE_EXPLORATION) + }, 1, constants.TECHNIQUE_FILE_EXPLORATION) + elif extract_workflows.is_file_workflow(os.path.join(repo_dir, file_path)): + workflow_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, + repo_dir, repo_relative_path, filename) + metadata_result.add_result(constants.CAT_WORKFLOWS, + { + constants.PROP_VALUE: workflow_url, + constants.PROP_TYPE: constants.URL + }, 1, constants.TECHNIQUE_FILE_EXPLORATION) elif repo_type == constants.RepositoryType.GITHUB: # if file_path.startswith(".github/workflows/"): # category = constants.CAT_WORKFLOWS @@ -220,7 +320,23 @@ def process_repository_files(repo_dir, metadata_result: Result, repo_type, owner repo_dir, repo_relative_path, filename) metadata_result.add_result(category, {constants.PROP_VALUE: workflow_url, constants.PROP_TYPE: constants.URL}, - 1, constants.TECHNIQUE_FILE_EXPLORATION) + 1, constants.TECHNIQUE_FILE_EXPLORATION) + + if filename.endswith(".ga") or filename.endswith(".cwl") or filename.endswith(".nf") or ( + filename.endswith(".snake") or filename.endswith( + ".smk") or "Snakefile" == filename_no_ext) or filename.endswith(".knwf") or filename.endswith( + ".t2flow") or filename.endswith(".dag") or filename.endswith(".kar") or filename.endswith( + ".wdl"): + analysis = extract_workflows.is_file_workflow(os.path.join(repo_dir, file_path)) + if analysis: + workflow_url = get_file_link(repo_type, file_path, owner, repo_name, repo_default_branch, + repo_dir, repo_relative_path, filename) + metadata_result.add_result(constants.CAT_WORKFLOWS, + { + constants.PROP_VALUE: workflow_url, + constants.PROP_TYPE: constants.URL + }, 1, constants.TECHNIQUE_FILE_EXPLORATION) + if 'citation' in metadata_result.results: for cit in metadata_result.results['citation']: scholarly_article = {} @@ -356,6 +472,33 @@ def get_file_content_or_link(repo_type, file_path, owner, repo_name, repo_defaul if license_info: result[constants.PROP_NAME] = license_info['name'] result[constants.PROP_SPDX_ID] = license_info['spdx_id'] + + if category is constants.CAT_AUTHORS: + result = {} + authors_list = parse_author_file(file_text) + for author_l in authors_list: + + author_data = { + "name": author_l.get("name"), + "type": constants.AGENT, + "value": author_l.get("name") + } + + if author_l.get("url") is not None: + author_data["url"] = author_l.get("url") + if author_l.get("email") is not None: + author_data["email"] = author_l.get("email") + if author_l["type"] == "Person": + if author_l.get("last_name") is not None: + author_data["last_name"] = author_l.get("last_name") + if author_l.get("given_name") is not None: + author_data["given_name"] = author_l.get("given_name") + metadata_result.add_result( + constants.CAT_AUTHORS, + author_data, + 1, + constants.TECHNIQUE_FILE_EXPLORATION, url + ) # Properties extraction from cff if format_result == 'cff': yaml_content = yaml.safe_load(file_text) @@ -364,13 +507,13 @@ def get_file_content_or_link(repo_type, file_path, owner, repo_name, repo_defaul identifiers = yaml_content.get("identifiers", []) url_citation = preferred_citation.get("url") or yaml_content.get("url") + if identifiers: + result[constants.CAT_IDENTIFIER] = identifiers + identifier_url = next((id["value"] for id in identifiers if id["type"] == "url"), None) identifier_doi = next((id["value"] for id in identifiers if id["type"] == "doi"), None) - + title = yaml_content.get("title") or preferred_citation.get("title", None) - # doi = preferred_citation.get("doi", None) - # url_citation = preferred_citation.get("url", None) - # authors = preferred_citation.get("authors", []) authors = yaml_content.get("authors", []) if identifier_doi: @@ -415,16 +558,8 @@ def get_file_content_or_link(repo_type, file_path, owner, repo_name, repo_defaul if author_list: result[constants.PROP_AUTHOR] = author_list - - - # author_names = ", ".join( - # f"{a.get('given-names', '').strip()} {a.get('family-names', '').strip()}".strip() - # for a in authors if a.get('given-names') and a.get('family-names') - # ) or None if title: result[constants.PROP_TITLE] = title - # if author_names: - # result[constants.PROP_AUTHOR] = author_names if final_url: result[constants.PROP_URL] = final_url if doi: @@ -510,9 +645,17 @@ def parse_codeowners_structured(dir_path, filename): line = line.strip() if line and not line.startswith("#"): parts = line.split() - path = parts[0] # Primera parte es el path o patrón - owners = parts[1:] # Lo demás son los propietarios + path = parts[0] + owners = parts[1:] codeowners.append({"path": path, "owners": owners}) return {"codeowners": codeowners} +def clean_text(text): + cleaned_lines = [] + for line in text.splitlines(): + printable_chars = sum(1 for c in line if c in string.printable) + if len(line) == 0 or (printable_chars / len(line)) > 0.9: + cleaned_lines.append(line) + return "\n".join(cleaned_lines) + diff --git a/src/somef_core/process_repository.py b/src/somef_core/process_repository.py index 280fc5e..2258e00 100644 --- a/src/somef_core/process_repository.py +++ b/src/somef_core/process_repository.py @@ -30,7 +30,6 @@ def is_gitlab(gitlab_server): api_url = f"https://{gitlab_server}/api/v4/projects" try: response = requests.get(api_url, timeout=5) - print(response.status_code) if response.status_code in [200, 401, 403]: return True except requests.RequestException: @@ -38,14 +37,51 @@ def is_gitlab(gitlab_server): return False # the same as requests.get(args).json(), but protects against rate limiting -def rate_limit_get(*args, backoff_rate=2, initial_backoff=1, **kwargs): +def rate_limit_get(*args, backoff_rate=2, initial_backoff=1, size_limit_mb=constants.SIZE_DOWNLOAD_LIMIT_MB, **kwargs): +# def rate_limit_get(*args, backoff_rate=2, initial_backoff=1, **kwargs): """Function to obtain how many requests we have pending with the GitHub API""" + + """GET request that handles rate limiting and prevents downloading excessively large files""" + size_limit_bytes = size_limit_mb * 1024 * 1024 + url = args[0] if args else kwargs.get("url") + if not url: + raise ValueError("Missing URL in rate_limit_get") + + parsed = urlparse(url) + is_api_request = "api.github.com" in parsed.netloc + content_length = None + # just verify size if NOT is a request to api.github.com + if not is_api_request: + try: + head_response = requests.get(url, stream=True, allow_redirects=True, **kwargs) + content_length = head_response.headers.get("Content-Length") + if content_length is not None: + size_bytes = int(content_length) + print(f"HEAD Content-Length: {size_bytes}") + if size_bytes > size_limit_bytes: + logging.warning( + f"Download size {size_bytes} bytes exceeds limit of {size_limit_bytes} bytes. Skipping download." + ) + return None, None + else: + # logging.warning(f"Could not determine file size for {url}. Skipping download.") + # return None, None + logging.warning(f"No Content-Length header for {url}. Proceeding with download anyway (unable to estimate size).") + except Exception as e: + logging.warning(f"HEAD/stream request failed: {e}. Continuing with GET...") + rate_limited = True - response = {} date = "" + response = {} while rate_limited: - response = requests.get(*args, **kwargs) - date = response.headers["Date"] + use_stream = not is_api_request and (content_length is None or int(content_length) > 10 * 1024 * 1024) + response = requests.get( + *args, + timeout=(constants.DOWNLOAD_TIMEOUT_SECONDS, constants.DOWNLOAD_TIMEOUT_SECONDS), + stream=use_stream, + **kwargs + ) + date = response.headers.get("Date", "") # Show rate limit information if available if "X-RateLimit-Remaining" in response.headers: rate_limit_remaining = response.headers["X-RateLimit-Remaining"] @@ -54,14 +90,54 @@ def rate_limit_get(*args, backoff_rate=2, initial_backoff=1, **kwargs): logging.info( "Remaining GitHub API requests: " + rate_limit_remaining + " ### Next rate limit reset at: " + str( date_reset)) - if 'message' in response and 'API rate limit exceeded' in response['message']: - rate_limited = True - logging.warning(f"rate limited. Backing off for {initial_backoff} seconds") - time.sleep(initial_backoff) - # increase the backoff for next time - initial_backoff *= backoff_rate - else: - rate_limited = False + + if not use_stream: + try: + json_data = response.json() + msg = json_data.get("message", "") + if "API rate limit exceeded" in msg: + rate_limited = True + logging.warning(f"Rate limited. Backing off for {initial_backoff} seconds") + time.sleep(initial_backoff) + initial_backoff *= backoff_rate + continue + except Exception: + pass + + rate_limited = False + + if not is_api_request and use_stream: + content = bytearray() + total_read = 0 + chunk_size = 1024 * 1024 # 1 MB + start_time = time.monotonic() + + try: + for i, chunk in enumerate(response.iter_content(chunk_size=chunk_size)): + if not chunk: + # logging.debug(f"Chunk {i} empty, continue...") + continue + + # logging.debug(f"Chunk read {i}: {len(chunk)} bytes") + content.extend(chunk) + total_read += len(chunk) + + # Comprobar límite de tamaño + if total_read > size_limit_bytes: + logging.warning(f"Downloaded content exceeded {size_limit_bytes} bytes. Aborting.") + return None, None + + # Comprobar límite de tiempo + elapsed = time.monotonic() - start_time + if elapsed > constants.DOWNLOAD_TIMEOUT_SECONDS: + logging.warning(f"Download exceeded time limit ({elapsed:.2f}s). Aborting.") + return None, None + + except Exception as e: + logging.warning(f"Error while streaming: {e}") + return None, None + + response._content = bytes(content) return response, date @@ -148,6 +224,26 @@ def load_gitlab_repository_metadata(repo_metadata: Result, repository_url): elif zip_gz_entry: value = zip_gz_entry["url"] + if category == constants.CAT_ASSETS: + assets_release_list_filtered = [] + for source in release[constants.CAT_ASSETS]['sources']: + source_asset = { + constants.PROP_ENCODING_FORMAT: source[constants.PROP_FORMAT], + constants.PROP_CONTENT_URL: source[constants.PROP_URL] + } + assets_release_list_filtered.append(source_asset) + + for link in release[constants.CAT_ASSETS]['links']: + link_asset = { + constants.PROP_NAME: link[constants.PROP_NAME], + constants.PROP_ENCODING_FORMAT: link["link_type"], + constants.PROP_URL: constants.PROP_URL, + constants.PROP_CONTENT_URL: link["direct_asset_url"], + } + assets_release_list_filtered.append(link_asset) + + value = assets_release_list_filtered + if value: release_obj[category] = value else: @@ -362,10 +458,17 @@ def download_readme(owner, repo_name, default_branch, repo_type, authorization): logging.info(f"Downloading {primary_url}") repo_download, date = rate_limit_get(primary_url, headers=header_template(authorization)) + + if repo_download is None: + logging.warning(f"Repository archive skipped due to size limit: {constants.SIZE_DOWNLOAD_LIMIT_MB} MB or content-lenght none") + return None if repo_download.status_code == 404: logging.error(f"Error: Archive request failed with HTTP {repo_download.status_code}") logging.info(f"Trying to download {secondary_url}") repo_download, date = rate_limit_get(secondary_url, headers=header_template(authorization)) + if repo_download is None: + logging.warning(f"Repository archive skipped due to size limit: {constants.SIZE_DOWNLOAD_LIMIT_MB} MB or content-lenght none") + return None if repo_download.status_code != 200: logging.error(f"Error: Archive request failed with HTTP {repo_download.status_code}") return None @@ -440,7 +543,12 @@ def load_online_repository_metadata(repository_metadata: Result, repository_url, date = "" if not ignore_api_metadata: general_resp_raw, date = rate_limit_get(repo_api_base_url, headers=header) + if general_resp_raw is None: + logging.warning(f"Repository archive skipped due to size limit: {constants.SIZE_DOWNLOAD_LIMIT_MB} MB or content-lenght none") + return repository_metadata, "", "", "" + general_resp = general_resp_raw.json() + if 'message' in general_resp: if general_resp['message'] == "Not Found": logging.error("Error: Repository name is private or incorrect") @@ -474,7 +582,7 @@ def load_online_repository_metadata(repository_metadata: Result, repository_url, value = '%s,' % (', '.join(value)) value = value.rstrip(',') if category in [constants.CAT_CODE_REPOSITORY, constants.CAT_ISSUE_TRACKER, - constants.CAT_DOWNLOAD_URL, constants.CAT_FORKS_URLS]: + constants.CAT_DOWNLOAD_URL, constants.CAT_FORKS_URLS, constants.CAT_HOMEPAGE]: value_type = constants.URL if category in [constants.CAT_DATE_CREATED, constants.CAT_DATE_UPDATED]: value_type = constants.DATE @@ -494,12 +602,13 @@ def load_online_repository_metadata(repository_metadata: Result, repository_url, constants.PROP_VALUE: value, constants.PROP_TYPE: value_type } - + if (result['value']): repository_metadata.add_result(category, result, 1, constants.TECHNIQUE_GITHUB_API) # get languages if not ignore_api_metadata: languages_raw, date = rate_limit_get(filtered_resp['languages_url'], headers=header) + languages = languages_raw.json() if "message" in languages: logging.error("Error while retrieving languages: " + languages["message"]) @@ -537,7 +646,6 @@ def load_online_repository_metadata(repository_metadata: Result, repository_url, value = { constants.PROP_NAME: value, constants.PROP_TYPE: release[constants.AGENT_TYPE] - } if value != "": release_obj[category] = value @@ -582,8 +690,7 @@ def get_path(obj, path): def do_crosswalk(data, crosswalk_table): output = {} - # print('------------data realeases') - # print(data) + for somef_key, path in crosswalk_table.items(): value = get_path(data, path) if value is not None: @@ -641,12 +748,20 @@ def download_github_files(directory, owner, repo_name, repo_ref, authorization): repo_archive_url = f"https://github.com/{owner}/{repo_name}/archive/{repo_ref}.zip" logging.info(f"Downloading {repo_archive_url}") repo_download, date = rate_limit_get(repo_archive_url, headers=header_template(authorization)) + + if repo_download is None: + logging.warning(f"Repository archive skipped due to size limit: {constants.SIZE_DOWNLOAD_LIMIT_MB} MB or not content lenght.") + return None + if repo_download.status_code == 404: logging.error(f"Error: Archive request failed with HTTP {repo_download.status_code}") repo_archive_url = f"https://github.com/{owner}/{repo_name}/archive/main.zip" logging.info(f"Trying to download {repo_archive_url}") repo_download, date = rate_limit_get(repo_archive_url, headers=header_template(authorization)) - + if repo_download is None: + logging.warning(f"Repository archive skipped due to size limit: {constants.SIZE_DOWNLOAD_LIMIT_MB} MB or not content lenght.") + return None + if repo_download.status_code != 200: sys.exit(f"Error: Archive request failed with HTTP {repo_download.status_code}") @@ -659,13 +774,19 @@ def download_github_files(directory, owner, repo_name, repo_ref, authorization): with open(repo_zip_file, "wb") as f: f.write(repo_zip) - with zipfile.ZipFile(repo_zip_file, "r") as zip_ref: - zip_ref.extractall(repo_extract_dir) - + try: + with zipfile.ZipFile(repo_zip_file, "r") as zip_ref: + zip_ref.extractall(repo_extract_dir) + except zipfile.BadZipFile: + logging.error("Downloaded archive is not a valid zip (repo may be empty)") + return None + repo_folders = os.listdir(repo_extract_dir) + if not repo_folders: + logging.warning("Repository archive is empty") + return None repo_dir = os.path.join(repo_extract_dir, repo_folders[0]) - return repo_dir @@ -715,34 +836,34 @@ def get_all_gitlab_releases(repo_api_base_url): while True: url = f"{repo_api_base_url}/releases?page={page}&per_page=100" - logging.info(f"Obteniendo releases desde: {url}") + logging.info(f"Getting releases from: {url}") response = requests.get(url) - logging.info(f"Respuesta: {response.status_code}") + logging.info(f"Response: {response.status_code}") content_type = response.headers.get("Content-Type", "") if response.status_code != 200 or "application/json" not in content_type: - logging.error(f"Error en la respuesta o no es JSON: {response.text}") - break # Termina el bucle si la respuesta no es válida + logging.error(f"Error in response or not JSON: {response.text}") + break try: releases = response.json() except requests.exceptions.JSONDecodeError as e: - logging.error(f"Error al decodificar JSON: {e}. Respuesta: {response.text}") + logging.error(f"Error decoding JSON: {e}. Response: {response.text}") break if not releases: - break # Si ya no hay releases, termina el bucle + break all_releases.extend(releases) - # Verifica si hay más páginas + # check if more pages next_page = response.headers.get("X-Next-Page") if not next_page: - break # Si no hay más páginas, termina el bucle + break # No more pages page = int(next_page) if not all_releases: - logging.warning("No se encontraron releases.") + logging.warning("Not releseases found.") return [] @@ -760,25 +881,24 @@ def get_all_gitlab_releases(repo_api_base_url): def get_gitlab_releases(project_id, base_url): """ - Obtiene las releases de un repositorio en GitLab sin autenticación. - - :param project_id: ID del proyecto en GitLab - :param base_url: URL base del GitLab donde está alojado el proyecto (ej: https://gitlab.in2p3.fr) - :return: Lista de releases con información relevante + Retrieves the releases of a GitLab repository without authentication. + + :param project_id: ID of the project in GitLab + :param base_url: Base URL of the GitLab where the project is hosted (e.g., https://gitlab.in2p3.fr) + :return: List of releases with relevant information """ releases_url = f"{base_url}/api/v4/projects/{project_id}/releases" - logging.info(f"Obteniendo releases desde: {releases_url}") + logging.info(f"Getting releases from: {releases_url}") response = requests.get(releases_url) if response.status_code != 200: - logging.error(f"Error obteniendo releases: {response.text}") + logging.error(f"Error getting releases: {response.text}") return [] releases_list = response.json() - # Filtrar información relevante release_list_filtered = [ { "url": release.get("description"), @@ -793,7 +913,6 @@ def get_gitlab_releases(project_id, base_url): # error when github url is wrong class GithubUrlError(Exception): - # print("The URL provided seems to be incorrect") pass @@ -821,7 +940,6 @@ def get_all_paginated_results(base_url, headers, per_page=100): while True: url = f"{base_url}?per_page={per_page}&page={page}" - print(url) response, _ = rate_limit_get(url, headers=headers) if response.status_code != 200: @@ -835,4 +953,4 @@ def get_all_paginated_results(base_url, headers, per_page=100): all_results.extend(page_data) page += 1 - return all_results \ No newline at end of file + return all_results diff --git a/src/somef_core/regular_expressions.py b/src/somef_core/regular_expressions.py index 27da864..6bfe346 100644 --- a/src/somef_core/regular_expressions.py +++ b/src/somef_core/regular_expressions.py @@ -3,40 +3,49 @@ import re import markdown import requests +import json import validators from .utils import constants from .process_results import Result from urllib.parse import urlparse + import bibtexparser def extract_title(unfiltered_text, repository_metadata: Result, readme_source) -> Result: + from .header_analysis import label_header """ - Regexp to extract title (first header) from a repository - Parameters - ---------- - @param unfiltered_text: repo text - @param repository_metadata: Result with the extractions so far - @param readme_source: url to the file used (for provenance) - - Returns - ------- - @returns a Result including the title (if found) - + Regexp to extract title (first header) from a repository + Parameters + ---------- + @param unfiltered_text: repo text + @param repository_metadata: Result with the extractions so far + @param readme_source: url to the file used (for provenance) + + Returns + ------- + @returns a Result including the title (if found) """ + html_text = markdown.markdown(unfiltered_text) splitted = html_text.split("\n") index = 0 limit = len(splitted) output = "" regex = r'<[^<>]+>' + while index < limit: line = splitted[index] if line.startswith(""): - output = re.sub(regex, '', line) + title = re.sub(regex, '', line).strip() + header_labels = label_header(title.lower()) + if not header_labels and title.lower() != "overview": + output = title break index += 1 + + # If the output is empty or none, the category doesn't make sense and shouldn't be displayed in the final result if has_valid_output(output): repository_metadata.add_result(constants.CAT_FULL_TITLE, @@ -63,7 +72,7 @@ def extract_title_old(unfiltered_text): # header declared with ==== title = "" if len(underline_header) != 0: - title = re.split('.+[=]+[\n]+', unfiltered_text)[0].strip() + title = re.split(r'.+[=]+[\n]+', unfiltered_text)[0].strip() else: # The first occurrence is assumed to be the title. title = re.findall(r'# .+', unfiltered_text)[0] @@ -72,7 +81,7 @@ def extract_title_old(unfiltered_text): title = title[1:].strip() # Remove other markup (links, etc.) if "[!" in title: - title = re.split('\[\!', title)[0].strip() + title = re.split(r'\[\!', title)[0].strip() return title @@ -111,7 +120,8 @@ def extract_readthedocs(readme_text, repository_metadata: Result, readme_source) } try: # if name of the repo is known then compare against the readthedocs one. Only add it if it's similar/same - name_in_link = re.findall('https://([^.]+)\.readthedocs\.io', link) + # name_in_link = re.findall('https://([^.]+)\.readthedocs\.io', link) + name_in_link = re.findall(r'https://([^.]+)\.readthedocs\.io', link) name_in_link = name_in_link[0] if name == "" or name_in_link.lower() == name.lower(): repository_metadata.add_result(constants.CAT_DOCUMENTATION, result, 1, @@ -424,6 +434,30 @@ def extract_package_distributions(unfiltered_text, repository_metadata: Result, constants.PROP_TYPE: constants.URL, constants.PROP_VALUE: output }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, readme_source) + + matches = re.findall(constants.REGEXP_PACKAGE_MANAGER, unfiltered_text, re.VERBOSE) + found_urls = set() + + for match in matches: + try: + response = requests.get(match, timeout=5) + final_url = response.url + except requests.RequestException: + final_url = match + + if final_url not in found_urls and has_valid_output(final_url): + found_urls.add(final_url) + repository_metadata.add_result( + constants.CAT_PACKAGE_DISTRIBUTION, + { + constants.PROP_TYPE: constants.URL, + constants.PROP_VALUE: final_url + }, + 1, + constants.TECHNIQUE_REGULAR_EXPRESSION, + readme_source + ) + return repository_metadata @@ -541,17 +575,232 @@ def extract_doi_badges(readme_text, repository_metadata: Result, source) -> Resu """ # regex = r'\[\!\[DOI\]([^\]]+)\]\(([^)]+)\)' # regex = r'\[\!\[DOI\]\(.+\)\]\(([^)]+)\)' + doi_badges = re.findall(constants.REGEXP_DOI, readme_text) # The identifier is in position 1. Position 0 is the badge id, which we don't want to export - for doi in doi_badges: - repository_metadata.add_result(constants.CAT_IDENTIFIER, + if not doi_badges: + match = re.search(constants.REGEXP_ZENODO_LATEST_DOI, readme_text) + badge_url = None + if match: + badge_url = match.group(1) + else: + match = re.search(constants.REGEXP_ZENODO_DOI, readme_text) + if match: + badge_url = match.group(0) + try: + if badge_url is not None: + response = requests.get(badge_url, allow_redirects=True, timeout=10) + match = re.search(constants.REGEXP_ZENODO_JSON_LD, + response.text, + re.DOTALL | re.IGNORECASE + ) + if match: + json_ld_text = match.group(1).strip() + try: + json_ld_data = json.loads(json_ld_text) + identifier = json_ld_data.get('identifier') + repository_metadata.add_result(constants.CAT_IDENTIFIER, + { + constants.PROP_TYPE: constants.URL, + constants.PROP_VALUE: identifier, + }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + except json.JSONDecodeError: + logging.warning("Error parsing Zenodo JSON-LD") + except requests.RequestException as e: + logging.warning(f"Error fetching DOI from Zenodo badge: {e}") + else: + + for doi in doi_badges: + repository_metadata.add_result(constants.CAT_IDENTIFIER, + { + constants.PROP_TYPE: constants.URL, + constants.PROP_VALUE: doi[1] + }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + + return repository_metadata + +def extract_project_homepage_badges(readme_text, repository_metadata: Result, source) -> Result: + """ + Function that takes the text of a readme file and searches if there are any project homepages. + Parameters + ---------- + @param readme_text: Text of the readme + @param repository_metadata: Result with all the findings in the repo + @param source: source file on top of which the extraction is performed (provenance) + Returns + ------- + @returns Result with the Sofware heritage badges found + """ + homepage_badges = re.findall(constants.REGEXP_PROJECT_HOMEPAGE, readme_text) + # The identifier is in position 1. Position 0 is the badge id, which we don't want to export + + for homepage in homepage_badges: + repository_metadata.add_result(constants.CAT_HOMEPAGE, { constants.PROP_TYPE: constants.URL, - constants.PROP_VALUE: doi[1] + constants.PROP_VALUE: homepage[1] }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + return repository_metadata +# def extract_readthedocs_badgeds(readme_text, repository_metadata: Result, source) -> Result: +# """ +# Function that takes the text of a readme file and searches if there are readthedocs badges. +# Parameters +# ---------- +# @param readme_text: Text of the readme +# @param repository_metadata: Result with all the findings in the repo +# @param source: source file on top of which the extraction is performed (provenance) +# Returns +# ------- +# @returns Result with the readthedocs badges found +# """ +# print("--------------------------> Extracting readthedocs badges") +# readthedocs_badges = re.findall(constants.REGEXP_READTHEDOCS_BADGES, readme_text, re.DOTALL) +# print(readthedocs_badges) +# for doc in readthedocs_badges: +# print(f'Doc found: {doc}') +# url = doc[0] or doc[1] +# if url: +# repository_metadata.add_result(constants.CAT_DOCUMENTATION, +# { +# constants.PROP_TYPE: constants.URL, +# constants.PROP_VALUE: url +# }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + +# return repository_metadata + + +def extract_readthedocs_badgeds(readme_text, repository_metadata: Result, source) -> Result: + """ + Function that takes the text of a readme file and searches if there are readthedocs badges. + Parameters + ---------- + @param readme_text: Text of the readme + @param repository_metadata: Result with all the findings in the repo + @param source: source file on top of which the extraction is performed (provenance) + Returns + ------- + @returns Result with the readthedocs badges found + """ + + urls = set() + + # RST + for match in re.findall(constants.REGEXP_READTHEDOCS_RST, readme_text): + print(match) + if isinstance(match, tuple): + urls.update([u for u in match if u]) + elif match: + urls.add(match) + + # Markdown + for match in re.findall(constants.REGEXP_READTHEDOCS_MD, readme_text): + if isinstance(match, tuple): + urls.update([u for u in match if u]) + elif match: + urls.add(match) + + # HTML + pattern_html = re.compile(constants.REGEXP_READTHEDOCS_HTML, flags=re.VERBOSE |re.DOTALL | re.IGNORECASE) + for match in pattern_html.findall(readme_text): + if isinstance(match, tuple): + urls.update([u for u in match if u]) + elif match: + urls.add(match) + + for url in urls: + if "pypi.org/project" in url: + category = constants.CAT_PACKAGE_DISTRIBUTION + else: + category = constants.CAT_DOCUMENTATION + + repository_metadata.add_result( + category, + { + constants.PROP_TYPE: constants.URL, + constants.PROP_VALUE: url + }, + 1, + constants.TECHNIQUE_REGULAR_EXPRESSION, + source + ) + + return repository_metadata + +# def extract_package_manager_badgeds(readme_text, repository_metadata: Result, source) -> Result: +# """ +# Function that takes the text of a readme file and searches if there are package manager badges. +# Parameters +# ---------- +# @param readme_text: Text of the readme +# @param repository_metadata: Result with all the findings in the repo +# @param source: source file on top of which the extraction is performed (provenance) +# Returns +# ------- +# @returns Result with the package badges found +# """ +# package_manager_badges = re.findall(constants.REGEXP_READTHEDOCS_BADGES, readme_text, re.DOTALL) +# for package in package_manager_badges: +# repository_metadata.add_result(constants.CAT_DOCUMENTATION, +# { +# constants.PROP_TYPE: constants.URL, +# constants.PROP_VALUE: package +# }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + + +# return repository_metadata + + +def extract_swh_badges(readme_text, repository_metadata: Result, source) -> Result: + """ + Function that takes the text of a readme file and searches if there are any Software Heritage (swh) badges. + Parameters + ---------- + @param readme_text: Text of the readme + @param repository_metadata: Result with all the findings in the repo + @param source: source file on top of which the extraction is performed (provenance) + Returns + ------- + @returns Result with the Sofware heritage badges found + """ + swh_badges = re.findall(constants.REGEXP_SWH, readme_text) + # The identifier is in position 1. Position 0 is the badge id, which we don't want to export + + for swh in swh_badges: + + identifier = extract_swh_identifier_from_url(swh[1]) + if identifier: + url_identifier = constants.SWH_ROOT + identifier + repository_metadata.add_result(constants.CAT_IDENTIFIER, + { + constants.PROP_TYPE: constants.URL, + constants.PROP_VALUE: url_identifier + }, 1, constants.TECHNIQUE_REGULAR_EXPRESSION, source) + + return repository_metadata + +def extract_swh_identifier_from_url(url: str) -> str | None: + """ + Function that look for a correct identifier en the swh url + """ + + # If anchor look for identifier + anchor_match = re.search(constants.REGEXP_SWH_ANCHOR, url) + if anchor_match: + return anchor_match.group(1) + + # If no anchor look for all identifiers + all_matches = re.findall(constants.REGEXP_SWH_ALL_IDENTIFIERS, url) + if all_matches: + for preferred_type in ['rev', 'snp', 'dir', 'cnt']: + for match in all_matches: + if f"swh:1:{preferred_type}:" in match: + return match + + return None + def extract_binder_links(readme_text, repository_metadata: Result, source) -> Result: """ Function that does a regex to extract binder and colab links used as reference in the readme. @@ -654,6 +903,7 @@ def detect_license_spdx(license_text, type): ------- A JSON dictionary with name and spdx id """ + for license_name, license_info in constants.LICENSES_DICT.items(): if re.search(license_info["regex"], license_text, re.IGNORECASE): if type == 'JSON': @@ -667,16 +917,28 @@ def detect_license_spdx(license_text, type): "name": license_name, "identifier": f"https://spdx.org/licenses/{license_info['spdx_id']}" } + for license_name, license_info in constants.LICENSES_DICT.items(): + spdx_id = license_info["spdx_id"] + if re.search(rf'\b{re.escape(spdx_id)}\b', license_text, re.IGNORECASE): + return { + "name": license_name, + "spdx_id": spdx_id, + "@id": f"https://spdx.org/licenses/{spdx_id}" + } return None -# def detect_license(license_text): -# for license_name, license_info in constants.LICENSES_DICT.items(): -# if re.search(license_info["regex"], license_text, re.IGNORECASE): -# return { -# "name": license_name, -# "identifier": f"https://spdx.org/licenses/{license_info['spdx_id']}" -# } -# return None +def detect_spdx_from_declared(value: str): + """ + Check if declared license matches an SPDX ID in LICENSES_DICT. + """ + for name, info in constants.LICENSES_DICT.items(): + if value == info["spdx_id"]: + return { + "name": name, + "spdx_id": info["spdx_id"], + "@id": f"https://spdx.org/licenses/{info['spdx_id']}" + } + return None def extract_scholarly_article_properties(bibtex_entry, scholarlyArticle, type): """ diff --git a/src/somef_core/somef_cli.py b/src/somef_core/somef_cli.py index 0188d3b..1f4fea0 100644 --- a/src/somef_core/somef_cli.py +++ b/src/somef_core/somef_cli.py @@ -1,5 +1,5 @@ import sys -from uu import encode +# from uu import encode import validators import logging @@ -13,11 +13,12 @@ from .utils import constants, markdown_utils from .parser import mardown_parser, create_excerpts from .export import json_export +from .extract_software_type import check_repository_type from urllib.parse import urlparse, quote def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, local_repo=None, ignore_github_metadata=False, readme_only=False, keep_tmp=None, authorization=None, - ignore_test_folder=True) -> Result: + ignore_test_folder=True,requirements_mode='all') -> Result: """ Main function to get the data through the command line Parameters @@ -32,6 +33,7 @@ def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, loc @param keep_tmp: path where to store TMP files in case SOMEF is instructed to keep them @param authorization: GitHub authorization token @param ignore_test_folder: Ignore contents of test folders + @param requiriments_mode: flag to indicate what requirements show in codemeta Returns ------- @@ -67,6 +69,7 @@ def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, loc logging.info(f"{servidor} is GitLab.") bGitLab = True + print(f"DEBUG: {servidor} is_gitlab = {bGitLab}") if bGitLab: repo_type = constants.RepositoryType.GITLAB repository_metadata, owner, repo_name, def_branch = process_repository.load_online_repository_metadata( @@ -86,22 +89,35 @@ def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, loc os.makedirs(keep_tmp, exist_ok=True) local_folder = process_repository.download_repository_files(owner, repo_name, def_branch, repo_type, keep_tmp, repo_url, authorization) - readme_text, full_repository_metadata = process_files.process_repository_files(local_folder, + if local_folder is not None: + readme_text, full_repository_metadata = process_files.process_repository_files(local_folder, repository_metadata, repo_type, owner, repo_name, def_branch, - ignore_test_folder) + ignore_test_folder) + repository_metadata = check_repository_type(local_folder, repo_name, full_repository_metadata) + else: + logging.error("Error processing the target repository") + return repository_metadata else: # Use a temp directory + with tempfile.TemporaryDirectory() as temp_dir: local_folder = process_repository.download_repository_files(owner, repo_name, def_branch, repo_type, temp_dir, repo_url, authorization) - readme_text, full_repository_metadata = process_files.process_repository_files(local_folder, - repository_metadata, - repo_type, owner, - repo_name, - def_branch, + if local_folder is not None: + readme_text, full_repository_metadata = process_files.process_repository_files(local_folder, + repository_metadata, + repo_type, owner, + repo_name, + def_branch, ignore_test_folder) + + repository_metadata = check_repository_type(local_folder, repo_name, full_repository_metadata) + else: + logging.error("Error processing the target repository") + return repository_metadata + if readme_text == "": logging.warning("README document does not exist in the target repository") except process_repository.GithubUrlError: @@ -130,7 +146,11 @@ def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, loc readme_unfiltered_text = markdown_utils.remove_comments(readme_unfiltered_text) repository_metadata, string_list = header_analysis.extract_categories(readme_unfiltered_text, repository_metadata) + + logging.info("Extracted categories from headers successfully.") readme_text_unmarked = markdown_utils.unmark(readme_text) + logging.info("readme text unmarked successfully.") + if readme_text_unmarked != "": try: readme_source = repository_metadata.results[constants.CAT_README_URL][0] @@ -141,12 +161,18 @@ def cli_get_data(threshold, ignore_classifiers, repo_url=None, doc_src=None, loc readme_source) repository_metadata = regular_expressions.extract_doi_badges(readme_unfiltered_text, repository_metadata, readme_source) + repository_metadata = regular_expressions.extract_swh_badges(readme_unfiltered_text, repository_metadata, + readme_source) + repository_metadata = regular_expressions.extract_project_homepage_badges(readme_unfiltered_text, repository_metadata, + readme_source) repository_metadata = regular_expressions.extract_title(readme_unfiltered_text, repository_metadata, readme_source) repository_metadata = regular_expressions.extract_binder_links(readme_unfiltered_text, repository_metadata, readme_source) repository_metadata = regular_expressions.extract_readthedocs(readme_unfiltered_text, repository_metadata, readme_source) + repository_metadata = regular_expressions.extract_readthedocs_badgeds(readme_unfiltered_text, repository_metadata, + readme_source) repository_metadata = regular_expressions.extract_repo_status(readme_unfiltered_text, repository_metadata, readme_source) repository_metadata = regular_expressions.extract_wiki_links(readme_unfiltered_text, repo_url, @@ -191,7 +217,8 @@ def run_cli(*, pretty=False, missing=False, keep_tmp=None, - ignore_test_folder=True + ignore_test_folder=True, + requirements_mode="all" ): """Function to run all the required components of the cli for a repository""" # check if it is a valid url @@ -225,7 +252,7 @@ def run_cli(*, encoded_url = encoded_url.replace(".","") #removing dots just in case repo_data = cli_get_data(threshold=threshold, ignore_classifiers=ignore_classifiers, repo_url=repo_url, ignore_github_metadata=ignore_github_metadata, readme_only=readme_only, - keep_tmp=keep_tmp, ignore_test_folder=ignore_test_folder) + keep_tmp=keep_tmp, ignore_test_folder=ignore_test_folder, requirements_mode=requirements_mode) if output is not None: output = output.replace(".json","") @@ -234,7 +261,7 @@ def run_cli(*, if codemeta_out is not None: codemeta_out = codemeta_out.replace(".json", "") codemeta_out = codemeta_out + "_" + encoded_url + ".json" - json_export.save_codemeta_output(repo_data.results, codemeta_out, pretty=pretty) + json_export.save_codemeta_output(repo_data.results, codemeta_out, pretty=pretty, requirements_mode= requirements_mode) except: logging.error("Error when processing repo: " + repo_url) else: @@ -255,7 +282,7 @@ def run_cli(*, if output is not None: json_export.save_json_output(repo_data.results, output, missing, pretty=pretty) if codemeta_out is not None: - json_export.save_codemeta_output(repo_data.results, codemeta_out, pretty=pretty) + json_export.save_codemeta_output(repo_data.results, codemeta_out, pretty=pretty, requirements_mode=requirements_mode) diff --git a/src/somef_core/test/test_JSON_export.py b/src/somef_core/test/test_JSON_export.py index 27dc464..befc47f 100644 --- a/src/somef_core/test/test_JSON_export.py +++ b/src/somef_core/test/test_JSON_export.py @@ -7,65 +7,70 @@ test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep - +test_data_api_json = str(Path(__file__).parent / "test_data" / "api_responses") + os.path.sep class TestJSONExport(unittest.TestCase): @classmethod def setUpClass(cls): """Runs somef_cli once and saves the JSON""" - cls.json_file = test_data_path + "test_json_widoco_export.json" - - somef_cli.run_cli(threshold=0.8, - ignore_classifiers=False, - repo_url="https://github.com/dgarijo/Widoco", - local_repo=None, - doc_src=None, - in_file=None, - output=cls.json_file, - graph_out=None, - graph_format="turtle", - codemeta_out=None, - pretty=True, - missing=False, - readme_only=False) + # cls.json_file = test_data_path + "test_json_widoco_export.json" + cls.api_results_file = test_data_api_json + "widoco_api_response.json" + with open(cls.api_results_file, "r", encoding="utf-8") as f: + cls.json_content= json.load(f) + + # somef_cli.run_cli(threshold=0.8, + # ignore_classifiers=False, + # repo_url="https://github.com/dgarijo/Widoco", + # local_repo=None, + # doc_src=None, + # in_file=None, + # output=cls.json_file, + # graph_out=None, + # graph_format="turtle", + # codemeta_out=None, + # pretty=True, + # missing=False, + # readme_only=False) - with open(cls.json_file, "r") as f: - cls.json_content = json.load(f) + # with open(cls.json_file, "r") as f: + # cls.json_content = json.load(f) - def test_issue_417(self): - """Checks whether a repository correctly extracts to Codemeta""" - somef_cli.run_cli(threshold=0.8, - ignore_classifiers=False, - repo_url="https://github.com/dgarijo/Widoco", - local_repo=None, - doc_src=None, - in_file=None, - output=None, - graph_out=None, - graph_format="turtle", - codemeta_out=test_data_path + "test-417.json-ld", - pretty=True, - missing=False, - readme_only=False) - - text_file = open(test_data_path + "test-417.json-ld", "r") - data = text_file.read() - text_file.close() - json_content = json.loads(data) - issue_tracker = json_content["issueTracker"] # JSON is in Codemeta format + # def test_issue_417(self): + # """Checks whether a repository correctly extracts to Codemeta""" + + + # somef_cli.run_cli(threshold=0.8, + # ignore_classifiers=False, + # repo_url="https://github.com/dgarijo/Widoco", + # local_repo=None, + # doc_src=None, + # in_file=None, + # output=None, + # graph_out=None, + # graph_format="turtle", + # codemeta_out=test_data_path + "test-417.json-ld", + # pretty=True, + # missing=False, + # readme_only=False) - #len(json_content["citation"]) - #codemeta category citation is now referencePublication - assert issue_tracker == 'https://github.com/dgarijo/Widoco/issues' and len(json_content["referencePublication"]) > 0 and \ - len(json_content["name"]) > 0 and len(json_content["identifier"]) > 0 and \ - len(json_content["description"]) > 0 and len(json_content["readme"]) > 0 and \ - len(json_content["author"]) > 0 and len(json_content["buildInstructions"]) > 0 and \ - len(json_content["softwareRequirements"]) > 0 and len(json_content["programmingLanguage"]) > 0 and \ - len(json_content["keywords"]) > 0 and len(json_content["logo"]) > 0 and \ - len(json_content["license"]) > 0 and len(json_content["dateCreated"]) > 0 + # text_file = open(test_data_path + "test-417.json-ld", "r") + # data = text_file.read() + # text_file.close() + # json_content = json.loads(data) + # issue_tracker = json_content["issueTracker"] # JSON is in Codemeta format + + # #len(json_content["citation"]) + # #codemeta category citation is now referencePublication + # assert issue_tracker == 'https://github.com/dgarijo/Widoco/issues' and len(json_content["referencePublication"]) > 0 and \ + # len(json_content["name"]) > 0 and len(json_content["identifier"]) > 0 and \ + # len(json_content["description"]) > 0 and len(json_content["readme"]) > 0 and \ + # len(json_content["author"]) > 0 and len(json_content["buildInstructions"]) > 0 and \ + # len(json_content["softwareRequirements"]) > 0 and len(json_content["programmingLanguage"]) > 0 and \ + # len(json_content["keywords"]) > 0 and len(json_content["logo"]) > 0 and \ + # len(json_content["license"]) > 0 and len(json_content["dateCreated"]) > 0 - os.remove(test_data_path + "test-417.json-ld") + # os.remove(test_data_path + "test-417.json-ld") def test_issue_311(self): """Checks if Codemeta export has labels defined outside Codemeta""" @@ -155,6 +160,8 @@ def test_issue_629(self): # os.remove(test_data_path + "test_issue_629.json") + + def test_issue_651(self): """Checks if keywords is in the missing categories because is empty""" somef_cli.run_cli(threshold=0.8, @@ -179,8 +186,9 @@ def test_issue_745(self): """Checks whether all the items in license has a spdx_id""" somef_cli.run_cli(threshold=0.8, ignore_classifiers=False, - repo_url="https://github.com/sunpy/sunpy", - local_repo=None, + # repo_url="https://github.com/sunpy/sunpy", + repo_url=None, + local_repo=test_data_repositories + "sunpy", doc_src=None, in_file=None, output=test_data_path + "test_issue_745.json", @@ -197,25 +205,269 @@ def test_issue_745(self): json_content = json.loads(data) licenses = json_content["license"] + # print('---------------------------') + # print(licenses) + for i, license_entry in enumerate(licenses): assert "spdx_id" in license_entry["result"], f"Missing 'spdx_id' in license{i}" assert license_entry["result"]["spdx_id"], f"'spdx_id' empty in license {i}" os.remove(test_data_path + "test_issue_745.json") + def test_issue_499(self): + """Checks whether a repository correctly extracts assets from release""" + + # somef_cli.run_cli(threshold=0.8, + # ignore_classifiers=False, + # repo_url="https://github.com/dgarijo/Widoco", + # local_repo=None, + # doc_src=None, + # in_file=None, + # output=test_data_path + "test-499.json-ld", + # graph_out=None, + # graph_format="turtle", + # codemeta_out= None, + # pretty=True, + # missing=False, + # readme_only=False) + + # text_file = open(test_data_path + "test-499.json-ld", "r") + # data = text_file.read() + # text_file.close() + # json_content = json.loads(data) + + assert "releases" in self.json_content, "Missing 'releases' key in JSON content" + assert isinstance(self.json_content["releases"], list), "'releases' should be a list" + + release_1425 = None + for release in self.json_content["releases"]: + if release.get("result", {}).get("tag") == "v1.4.25": + release_1425 = release + break + + assert release_1425 is not None, "No release with tag 'v1.4.25' found" + + assets = release_1425.get("result", {}).get("assets", []) + assert any(asset.get("name") == "widoco-1.4.25-jar-with-dependencies_JDK-11.jar" for asset in assets), \ + "Asset 'widoco-1.4.25-jar-with-dependencies_JDK-11.jar' not found in release v1.4.25" + + # os.remove(test_data_path + "test-499.json-ld") + + def test_issue_577(self): + """Checks if there are idenfiers from Software Heritage in the README file""" + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + doc_src=test_data_path + "README-widoco-swh.md", + in_file=None, + output=test_data_path + "test-577.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=True) + + with open(test_data_path + "test-577.json", "r") as text_file: + data = json.load(text_file) + + expected_values = { + "https://doi.org/10.5281/zenodo.11093793", + "https://archive.softwareheritage.org/swh:1:rev:fec66b89a4f4acb015a44c7f8cb671d49bec626a" + } + identifiers = data.get("identifier", []) + found_values = set() + + for item in identifiers: + value = item["result"]["value"] + found_values.add(value) + + for expected in expected_values: + assert expected in found_values, f"Expected identifier not found: {expected}" + + os.remove(test_data_path + "test-577.json") + + + def test_issue_580(self): + """Checks if there are Project homepage in the readme file""" + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + doc_src=test_data_path + "README-citation-file-format.md", + in_file=None, + output=test_data_path + "test-580.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=True) + + with open(test_data_path + "test-580.json", "r") as text_file: + data = json.load(text_file) + + found = False + homepage_entries = data.get("homepage", []) + print('---------------------------') + print(homepage_entries) + for item in homepage_entries: + technique = item.get("technique") + result = item.get("result", {}) + value = result.get("value") + + if technique == "regular_expression" and value == "https://citation-file-format.github.io": + found = True + break + + assert found, "Expected homepage not found" + + os.remove(test_data_path + "test-580.json") + def test_issue_653(self): """Checks if json from widoco repo has more than 30 releases""" assert len(self.json_content["releases"]) > 30, f"Expected more than 30 releases, found {len(self.json_content['release'])}" - @classmethod - def tearDownClass(cls): - """delete temp file JSON just if all the test pass""" - if os.path.exists(cls.json_file): - try: - os.remove(cls.json_file) - print(f"Deleted {cls.json_file}") - except Exception as e: - print(f"Failed to delete {cls.json_file}: {e}") - -if __name__ == '__main__': - unittest.main() + def test_not_recursive_folders(self): + """ + Checks that build files in subfolders are ignored if they already exist in the root, + and that duplicates do not appear in the results. + pom.xml has been duplicated in docs/pom.xml + """ + + output_path = test_data_path + 'test_widoco_not_recursive_folders.json' + + somef_cli.run_cli( threshold=0.8, + local_repo=test_data_repositories + "Widoco", + doc_src=None, + in_file=None, + output=output_path, + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=False, + readme_only=False) + + + with open(output_path, "r") as f: + json_content = json.load(f) + + build_files = [ + entry[constants.PROP_RESULT][constants.PROP_VALUE] + for key in json_content + for entry in json_content[key] + if key == constants.CAT_HAS_BUILD_FILE + ] + + # root + assert any("pom.xml" in bf for bf in build_files), "The root pom.xml should be present" + # No docs/pom.xml + assert not any("docs/pom.xml" in bf for bf in build_files), "The pom.xml in docs/ should not be processed" + assert len(build_files) == len(set(build_files)), "There should be no duplicate build files" + + + def test_runtime_platform(self): + """ + Checks that the runtime_platform information is correctly extracted from the project. + """ + + runtime_entries = [ + entry[constants.PROP_RESULT] + for key in self.json_content + for entry in self.json_content[key] + if key == constants.CAT_RUNTIME_PLATFORM + ] + + assert len(runtime_entries) > 0, "There should be at least one runtime_platform entry" + + found_java = any( + entry.get("name") == "Java" and entry.get("value") == "Java: 1.8" + for entry in runtime_entries + ) + assert found_java, "Java runtime with value Java: 1.8 should be present" + + + def test_issue_830(self): + """Checks if citattion have identifiers """ + citation = self.json_content.get("citation", []) + assert citation, "No 'citation' found in JSON" + assert any( + entry.get("result", {}).get("format") == "cff" + and any(id.get("value") == "10.5281/zenodo.591294" + for id in entry.get("result", {}).get("identifier", []) + ) + for entry in citation + ), "Citation.cff must have identifier id 10.5281/zenodo.591294" + + # @classmethod + # def tearDownClass(cls): + # """delete temp file JSON just if all the test pass""" + # if os.path.exists(cls.json_file): + # try: + # os.remove(cls.json_file) + # print(f"Deleted {cls.json_file}") + # except Exception as e: + # print(f"Failed to delete {cls.json_file}: {e}") + + def test_issue_862(self): + """Checks if this repository does not gets stuck when labeling headers""" + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + local_repo=test_data_repositories + "componentInstaller", + doc_src=None, + in_file=None, + output=test_data_path + "test_issue_862.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=False, + readme_only=False) + + text_file = open(test_data_path + "test_issue_862.json", "r") + data = text_file.read() + text_file.close() + json_content = json.loads(data) + + assert "description" in json_content, "Missing 'description' property" + + assert len(json_content["description"]) > 0, "Description list is empty" + + first_desc = json_content["description"][0]["result"] + assert "value" in first_desc, "Missing 'value' in description result" + assert first_desc["value"], "Description 'value' is empty" + + os.remove(test_data_path + "test_issue_862.json") + + def test_issue_859(self): + """Checks whether a repository without content works fine. Must have just some results from the API.""" + + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url="https://github.com/shiningZZ/GU-CAFF", + local_repo=None, + doc_src=None, + in_file=None, + output=test_data_path + "test-859.json", + graph_out=None, + graph_format="turtle", + codemeta_out= None, + pretty=True, + missing=False, + readme_only=False) + + with open(test_data_path + "test-859.json", "r") as text_file: + json_content = json.load(text_file) + + assert "code_repository" in json_content + assert len(json_content["code_repository"]) > 0 + + for key, entries in json_content.items(): + if isinstance(entries, list): + for entry in entries: + assert entry.get("technique") == "GitHub_API", \ + f"Unexpected technique {entry.get('technique')} in key {key}" + + os.remove(test_data_path + "test-859.json") + + + \ No newline at end of file diff --git a/src/somef_core/test/test_bower_parser 2.py b/src/somef_core/test/test_bower_parser 2.py new file mode 100644 index 0000000..9a2ad9d --- /dev/null +++ b/src/somef_core/test/test_bower_parser 2.py @@ -0,0 +1,111 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.bower_parser import parse_bower_json_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestBowerParser(unittest.TestCase): + + def test_parse_bower_json(self): + bower_file_path = test_data_repositories + os.path.sep + "js-template" + os.path.sep + "bower.json" + + result = Result() + + # metadata_result = parse_bower_json_file(bower_file_path, result, "https://example.org/bower.json") + metadata_result = parse_bower_json_file(bower_file_path, result, bower_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bower.json") + self.assertEqual(package_results[0]["result"]["value"], bower_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + name_results = metadata_result.results.get(constants.CAT_NAME, []) + self.assertTrue(len(name_results) > 0, "No name found") + self.assertEqual(name_results[0]["result"]["value"], "alarm") + self.assertEqual(name_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Alarm clock project during week1 day2 JS at Epicodus.") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + # there is a homepage with "" in the bower. None, null and "" must not show in metadatos + + # homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + # self.assertTrue(len(homepage_results) > 0, "No homepage found") + # self.assertEqual(homepage_results[0]["result"]["value"], "") + # self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertEqual(len(homepage_results), 0, "Expected no homepage for this bower.json") + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "ISC") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) > 0, "No authors found") + self.assertEqual(len(authors_results), 2, "Expected two authors") + + self.assertEqual(authors_results[0]["result"]["value"], "Andrew Accuardi ") + self.assertEqual(authors_results[1]["result"]["value"], "Another Author ") + + found_jquery = False + found_bootstrap = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "jquery" and dependency.get("dependency_type") == "runtime": + found_jquery = True + self.assertTrue(found_jquery, "jQuery dependency not found") + + def test_parse_2_bower_json(self): + bower_file_path = test_data_repositories + os.path.sep + "chosen" + os.path.sep + "bower.json" + + result = Result() + + # metadata_result = parse_bower_json_file(bower_file_path, result, "https://example.org/bower.json") + metadata_result = parse_bower_json_file(bower_file_path, result, bower_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bower.json") + self.assertEqual(package_results[0]["result"]["value"], bower_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + name_results = metadata_result.results.get(constants.CAT_NAME, []) + self.assertTrue(len(name_results) > 0, "No name found") + self.assertEqual(name_results[0]["result"]["value"], "chosen") + self.assertEqual(name_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Chosen is a JavaScript plugin that makes select boxes user-friendly. It is currently available in both jQuery and Prototype flavors.") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertEqual(homepage_results[0]["result"]["value"], "https://harvesthq.github.io/chosen/") + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "https://github.com/harvesthq/chosen/blob/master/LICENSE.md") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) > 0, "No authors found") + self.assertEqual(len(authors_results), 4, "Expected two authors") + + self.assertEqual(authors_results[0]["result"]["value"], "Patrick Filler") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_bower_parser.py b/src/somef_core/test/test_bower_parser.py new file mode 100644 index 0000000..9a2ad9d --- /dev/null +++ b/src/somef_core/test/test_bower_parser.py @@ -0,0 +1,111 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.bower_parser import parse_bower_json_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestBowerParser(unittest.TestCase): + + def test_parse_bower_json(self): + bower_file_path = test_data_repositories + os.path.sep + "js-template" + os.path.sep + "bower.json" + + result = Result() + + # metadata_result = parse_bower_json_file(bower_file_path, result, "https://example.org/bower.json") + metadata_result = parse_bower_json_file(bower_file_path, result, bower_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bower.json") + self.assertEqual(package_results[0]["result"]["value"], bower_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + name_results = metadata_result.results.get(constants.CAT_NAME, []) + self.assertTrue(len(name_results) > 0, "No name found") + self.assertEqual(name_results[0]["result"]["value"], "alarm") + self.assertEqual(name_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Alarm clock project during week1 day2 JS at Epicodus.") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + # there is a homepage with "" in the bower. None, null and "" must not show in metadatos + + # homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + # self.assertTrue(len(homepage_results) > 0, "No homepage found") + # self.assertEqual(homepage_results[0]["result"]["value"], "") + # self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertEqual(len(homepage_results), 0, "Expected no homepage for this bower.json") + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "ISC") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) > 0, "No authors found") + self.assertEqual(len(authors_results), 2, "Expected two authors") + + self.assertEqual(authors_results[0]["result"]["value"], "Andrew Accuardi ") + self.assertEqual(authors_results[1]["result"]["value"], "Another Author ") + + found_jquery = False + found_bootstrap = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "jquery" and dependency.get("dependency_type") == "runtime": + found_jquery = True + self.assertTrue(found_jquery, "jQuery dependency not found") + + def test_parse_2_bower_json(self): + bower_file_path = test_data_repositories + os.path.sep + "chosen" + os.path.sep + "bower.json" + + result = Result() + + # metadata_result = parse_bower_json_file(bower_file_path, result, "https://example.org/bower.json") + metadata_result = parse_bower_json_file(bower_file_path, result, bower_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bower.json") + self.assertEqual(package_results[0]["result"]["value"], bower_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + name_results = metadata_result.results.get(constants.CAT_NAME, []) + self.assertTrue(len(name_results) > 0, "No name found") + self.assertEqual(name_results[0]["result"]["value"], "chosen") + self.assertEqual(name_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Chosen is a JavaScript plugin that makes select boxes user-friendly. It is currently available in both jQuery and Prototype flavors.") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertEqual(homepage_results[0]["result"]["value"], "https://harvesthq.github.io/chosen/") + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "https://github.com/harvesthq/chosen/blob/master/LICENSE.md") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) > 0, "No authors found") + self.assertEqual(len(authors_results), 4, "Expected two authors") + + self.assertEqual(authors_results[0]["result"]["value"], "Patrick Filler") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_cabal_parser 2.py b/src/somef_core/test/test_cabal_parser 2.py new file mode 100644 index 0000000..3efddc2 --- /dev/null +++ b/src/somef_core/test/test_cabal_parser 2.py @@ -0,0 +1,94 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.cabal_parser import parse_cabal_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestCabalParser(unittest.TestCase): + + def test_parse_cabal(self): + cabal_file_path = test_data_repositories + os.path.sep + "unused" + os.path.sep + "unused.cabal" + result = Result() + + # metadata_result = parse_cabal_file(cabal_file_path, result, "https://example.org/unused.cabal") + metadata_result = parse_cabal_file(cabal_file_path, result, cabal_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "unused.cabal") + self.assertEqual(package_results[0]["result"]["value"], cabal_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "unused") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Please see README.md") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "https://github.com/joshuaclayton/unused#readme") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + found_dep = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "terminal-progress-bar" and dependency.get("dependency_type") == "runtime": + found_dep = True + self.assertTrue(found_dep, "Dependency not found") + + def test_parse_2_cabal(self): + cabal_file_path = test_data_repositories + os.path.sep + "haskell" + os.path.sep + "cabal.cabal" + result = Result() + + # metadata_result = parse_cabal_file(cabal_file_path, result, "https://example.org/cabal.cabal") + metadata_result = parse_cabal_file(cabal_file_path, result, cabal_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "cabal.cabal") + self.assertEqual(package_results[0]["result"]["value"], cabal_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + expected_start = "The Haskell Common Architecture" + + self.assertTrue( + description_results[0]["result"]["value"].strip().startswith(expected_start) + ) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "http://www.haskell.org/cabal/") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "BSD-3-Clause") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertEqual(requirements_results[0]["result"]["name"], "Cabal-syntax") + self.assertEqual(requirements_results[1]["result"]["version"], ">= 0.4.0.1 && < 0.6") + + issue_tracker_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) + self.assertEqual(issue_tracker_results[0]["result"]["value"], "https://github.com/haskell/cabal/issues") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_cabal_parser.py b/src/somef_core/test/test_cabal_parser.py new file mode 100644 index 0000000..3efddc2 --- /dev/null +++ b/src/somef_core/test/test_cabal_parser.py @@ -0,0 +1,94 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.cabal_parser import parse_cabal_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestCabalParser(unittest.TestCase): + + def test_parse_cabal(self): + cabal_file_path = test_data_repositories + os.path.sep + "unused" + os.path.sep + "unused.cabal" + result = Result() + + # metadata_result = parse_cabal_file(cabal_file_path, result, "https://example.org/unused.cabal") + metadata_result = parse_cabal_file(cabal_file_path, result, cabal_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "unused.cabal") + self.assertEqual(package_results[0]["result"]["value"], cabal_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "unused") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "Please see README.md") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "https://github.com/joshuaclayton/unused#readme") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + found_dep = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "terminal-progress-bar" and dependency.get("dependency_type") == "runtime": + found_dep = True + self.assertTrue(found_dep, "Dependency not found") + + def test_parse_2_cabal(self): + cabal_file_path = test_data_repositories + os.path.sep + "haskell" + os.path.sep + "cabal.cabal" + result = Result() + + # metadata_result = parse_cabal_file(cabal_file_path, result, "https://example.org/cabal.cabal") + metadata_result = parse_cabal_file(cabal_file_path, result, cabal_file_path) + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "cabal.cabal") + self.assertEqual(package_results[0]["result"]["value"], cabal_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + expected_start = "The Haskell Common Architecture" + + self.assertTrue( + description_results[0]["result"]["value"].strip().startswith(expected_start) + ) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "http://www.haskell.org/cabal/") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "BSD-3-Clause") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertEqual(requirements_results[0]["result"]["name"], "Cabal-syntax") + self.assertEqual(requirements_results[1]["result"]["version"], ">= 0.4.0.1 && < 0.6") + + issue_tracker_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) + self.assertEqual(issue_tracker_results[0]["result"]["value"], "https://github.com/haskell/cabal/issues") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_cli.py b/src/somef_core/test/test_cli.py index fa548e5..fc27ed5 100644 --- a/src/somef_core/test/test_cli.py +++ b/src/somef_core/test/test_cli.py @@ -296,6 +296,7 @@ def test_issue_319_1(self): assert data.find(constants.FORMAT_CFF) > 0 os.remove(test_data_path + "test-319-1.json") + def test_issue_319_2(self): """Test checks that the output format of citation files is specified in the output""" somef_cli.run_cli(threshold=0.8, @@ -406,17 +407,19 @@ def test_issue_314(self): def test_issue_314_1(self): """Checks that the program can be run using only a single readme. GitHub""" somef_cli.run_cli(threshold=0.8, - ignore_classifiers=False, - repo_url="https://github.com/tensorflow/tensorflow/tree/v2.6.0", - doc_src=None, - in_file=None, - output=test_data_path + "test-314-1.json", - graph_out=None, - graph_format="turtle", - codemeta_out=None, - pretty=True, - missing=True, - readme_only=True) + ignore_classifiers=False, + # repo_url="https://github.com/tensorflow/tensorflow/tree/v2.6.0", + repo_url=None, + # doc_src=None, + doc_src= test_data_path + "README-tensorflow-2.6.0.md", + in_file=None, + output=test_data_path + "test-314-1.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=True, + readme_only=True) text_file = open(test_data_path + "test-314-1.json", "r") data = text_file.read() text_file.close() @@ -425,11 +428,14 @@ def test_issue_314_1(self): assert image is not None os.remove(test_data_path + "test-314-1.json") + def test_issue_403(self): """Checks that the readme link returned by somef is correct""" somef_cli.run_cli(threshold=0.8, ignore_classifiers=False, repo_url="https://github.com/oeg-upm/wot-hive", + # repo_url=None, + # local_repo=test_data_repositories + "wot-hive", doc_src=None, in_file=None, output=test_data_path + "test-403.json", @@ -489,7 +495,6 @@ def test_issue_225_406(self): text_file = open(test_data_path + "test-225.json", "r") data = text_file.read() text_file.close() - print(data) assert data.find("\"" + constants.PROP_FORMAT + "\": \"" + constants.FORMAT_WIKI + "\"") os.remove(test_data_path + "test-225.json") @@ -517,18 +522,20 @@ def test_issue_406(self): def test_issue_255(self): """Tests if somef can detect wiki articles""" somef_cli.run_cli(threshold=0.8, - ignore_classifiers=False, - repo_url="https://github.com/mbloch/mapshaper/", - local_repo=None, - doc_src=None, - in_file=None, - output=test_data_path + "test-255.json", - graph_out=None, - graph_format="turtle", - codemeta_out=None, - pretty=True, - missing=True, - readme_only=False) + ignore_classifiers=False, + # repo_url="https://github.com/mbloch/mapshaper/", + repo_url=None, + local_repo=None, + # doc_src=None, + doc_src=test_data_path + "README-mapshaper.md", + in_file=None, + output=test_data_path + "test-255.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=True, + readme_only=False) text_file = open(test_data_path + "test-255.json", "r") data = text_file.read() text_file.close() @@ -661,6 +668,7 @@ def test_issue_366(self): assert data.find(constants.FORMAT_DOCKERFILE) >= 0 os.remove(test_data_path + "test-366.json") + def test_issue_443(self): somef_cli.run_cli(threshold=0.8, ignore_classifiers=False, @@ -705,6 +713,7 @@ def test_issue_443_3(self): assert description is not None os.remove(test_data_path + "test-443.json") + def test_issue_556(self): """ This test assesses whether documentation links that have been commented in the readme out are ignored. @@ -778,3 +787,5 @@ def test_issue_567(self): text_file.close() assert constants.CAT_ACKNOWLEDGEMENT not in json_content os.remove(test_data_path + "repositories/software_catalog/test-567.json") + + diff --git a/src/somef_core/test/test_codemeta_export.py b/src/somef_core/test/test_codemeta_export.py index e40b261..2277aca 100644 --- a/src/somef_core/test/test_codemeta_export.py +++ b/src/somef_core/test/test_codemeta_export.py @@ -3,34 +3,57 @@ import json from pathlib import Path from .. import somef_cli +from ..parser import pom_xml_parser +from ..export import json_export test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep +test_data_api_json = str(Path(__file__).parent / "test_data" / "api_responses") + os.path.sep class TestCodemetaExport(unittest.TestCase): - + + @classmethod def setUpClass(cls): """Runs somef_cli once and saves the JSON""" cls.json_file = test_data_path + "test_json_codemeta_export.json" - somef_cli.run_cli( - threshold=0.8, - ignore_classifiers=False, - repo_url="https://github.com/tpronk/somef-demo-repo/", - doc_src=None, - in_file=None, - output=None, - graph_out=None, - graph_format="turtle", - codemeta_out=cls.json_file, + cls.api_results_file = test_data_api_json + "somef-demo.json" + with open(cls.api_results_file, "r", encoding="utf-8") as f: + cls.api_results = json.load(f) + + json_export.save_codemeta_output( + cls.api_results, + cls.json_file, pretty=True, - missing=True, - readme_only=False + requirements_mode=False ) - with open(cls.json_file, "r") as f: + with open(cls.json_file, "r", encoding="utf-8") as f: cls.json_content = json.load(f) + # somef_cli.run_cli( + # threshold=0.8, + # ignore_classifiers=False, + # repo_url="https://github.com/juanjemdIos/somef-demo-repo/", + # # repo_url=None, + # # local_repo= test_data_repositories + "somef-demo", + # doc_src=None, + # in_file=None, + # output=None, + # graph_out=None, + # graph_format="turtle", + # codemeta_out=cls.json_file, + # pretty=True, + # missing=True, + # readme_only=False + # ) + + # with open(cls.json_file, "r") as f: + # cls.json_content = json.load(f) + + # print(cls.json_content) + def test_codemeta_version(self): """Checks if codemeta version is v3""" @@ -210,18 +233,302 @@ def test_codemeta_relevants_programming_languages(self): expected_languages = ["Jupyter Notebook"] assert set(self.json_content["programmingLanguage"]) == set(expected_languages), f"Mismatch: {self.json_content['programmingLanguage']}" + def test_codemeta_author_file(self): + """Checks if codemeta file has extracted the authors in the author file""" + authors = [author.get("name") for author in self.json_content["author"] if author["@type"] == "Person"] + expected_authors = {"Daniel Garijo", "Juanje Mendoza"} + assert set(authors) >= expected_authors, f"Mismatch in authors: {authors}" + + def test_issue_763(self): + """ + Checks that several citations of same item in json become in one in codemeta + + Export to codemeta: Reconcile Bibtex and CFF exports + """ + + somef_cli.run_cli(threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "inspect4py", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out= test_data_path + 'test_codemeta_several_citations.json', + pretty=True, + missing=False) + + json_file_path = test_data_path + "test_codemeta_several_citations.json" + text_file = open(json_file_path, "r") + data = text_file.read() + json_content = json.loads(data) + text_file.close() + + reference_publications = json_content.get("referencePublication", []) + + # just one reference + assert len(reference_publications) == 1, f"Expected 1 referencePublication, found {len(reference_publications)}" + + # reference with doi expected + assert reference_publications[0].get("identifier") == "10.1145/3524842.3528497", \ + f"Expected identifier '10.1145/3524842.3528497', found '{reference_publications[0].get('identifier')}'" + os.remove(json_file_path) + + def test_codemeta_duplicate_dois(self): + """Checks if codemeta duplicates dois whith diferent format: doi.org, dx.doi....""" + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + doc_src=test_data_path + "README-widoco-duplicate-dois.md", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out=test_data_path + 'test_codemeta_dup_dois.json', + pretty=True, + missing=True) + + json_file_path = test_data_path + "test_codemeta_dup_dois.json" + # check if the file has been created in the correct path + assert os.path.exists(json_file_path), f"File {json_file_path} doesn't exist." + + with open(json_file_path, "r") as f: + codemeta = json.load(f) + + ref_pubs = codemeta.get("referencePublication", []) + + dois = set() + for pub in ref_pubs: + if isinstance(pub, dict) and "identifier" in pub: + dois.add(pub["identifier"]) + assert len(dois) == 1, f"Expected 1 DOI, got {len(dois)}: {dois}" + + os.remove(json_file_path) + + def test_requirements_mode(self): + + """ + Checks that when requirements_mode='v', only structured requirements from code parsers are exported, + and textual requirements (e.g. from README or codemeta.json) are excluded. + """ + output_path = test_data_path + 'test_codemeta_widoco_requirements_v.json' + + somef_cli.run_cli(threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "Widoco", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out= output_path, + pretty=True, + missing=False, + requirements_mode="v") + + with open(output_path, "r") as f: + json_content = json.load(f) + + requirements = json_content.get("softwareRequirements", []) + + assert all(isinstance(req, dict) and "name" in req for req in requirements), \ + f"Expected only structured requirements, found: {requirements}" + + assert all(not isinstance(req, str) for req in requirements), \ + f"Found unexpected textual requirement entries: {[r for r in requirements if isinstance(r, str)]}" + + os.remove(output_path) + + def test_requirements_not_duplicate(self): + + """ + Checks that when requirements_mode='all', the exported softwareRequirements list contains no duplicates, + even if the same requirement appears from multiple sources or techniques. + """ + output_path = test_data_path + 'test_codemeta_widoco_requirements_not_duplicate.json' + + somef_cli.run_cli(threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "Widoco", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out= output_path, + pretty=True, + missing=False, + requirements_mode="all") + + with open(output_path, "r") as f: + json_content = json.load(f) + + requirements = json_content.get("softwareRequirements", []) + + seen = set() + for req in requirements: + if isinstance(req, dict): + key = f"{req['name'].strip()}|{req.get('version', '').strip()}" + else: + key = " ".join(req.strip().replace("\n", " ").split()) + assert key not in seen, f"Duplicate requirement found: {key}" + seen.add(key) + + os.remove(output_path) + + + def test_description_not_duplicate(self): + """ + Checks that the 'description' field in the exported codemeta contains no duplicate entries, + even if the same description appears from multiple sources or techniques. + """ + + output_path = test_data_path + 'test_codemeta_widoco_description_not_duplicate.json' + + somef_cli.run_cli( + threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "Widoco", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out=output_path, + pretty=True, + missing=False, + requirements_mode="all" + ) + + with open(output_path, "r") as f: + json_content = json.load(f) + + descriptions = json_content.get("description", []) + os.remove(output_path) + + seen = set() + for desc in descriptions: + normalized = " ".join(desc.strip().replace("\n", " ").split()) + assert normalized not in seen, f"Duplicate description found: {normalized}" + seen.add(normalized) + + + def test_codemeta_runtime(self): + + """ + Checks runtime in codemeta file + """ + + pom_xml_parser.processed_pom = False + + output_path = test_data_path + 'test_codemeta_widoco_runtime_platform.json' + if os.path.exists(output_path): + os.remove(output_path) + + somef_cli.run_cli(threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "Widoco", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out= output_path, + pretty=True, + missing=False, + requirements_mode="v") + + with open(output_path, "r") as f: + json_content = json.load(f) + + runtime = json_content.get("runtimePlatform", []) + assert runtime == "Java: 1.8", f"It was expected 'Java: 1.8' but it was '{runtime}'" + os.remove(output_path) + + def test_issue_832_join_authors(self): + """ + Check that an author who appears multiple times in the JSON appears only once in the Codemeta output, merging their properties. + """ + + somef_cli.run_cli(threshold=0.9, + ignore_classifiers=False, + repo_url=None, + doc_src=None, + local_repo=test_data_repositories + "fuji", + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out= test_data_path + 'test_codemeta_join_authors.json', + pretty=True, + missing=False) + + json_file_path = test_data_path + "test_codemeta_join_authors.json" + text_file = open(json_file_path, "r") + data = text_file.read() + json_content = json.loads(data) + text_file.close() + + authors = json_content.get("author", []) + assert len(authors) == 9, f"Expected 9 author, found {len(authors)}" + assert authors[0].get("name") == "Robert Huber", "Second author must be Robert Huber" + assert authors[1].get("email") == "anusuriya.devaraju@googlemail.com", \ + "Third author must have email anusuriya.devaraju@googlemail.com" + + os.remove(json_file_path) + + def test_issue_417(self): + """Checks whether a repository correctly extracts to Codemeta""" + + + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + local_repo=test_data_repositories + "Widoco", + doc_src=None, + in_file=None, + output=None, + graph_out=None, + graph_format="turtle", + codemeta_out=test_data_path + "test-417.json-ld", + pretty=True, + missing=False, + readme_only=False) + + text_file = open(test_data_path + "test-417.json-ld", "r") + data = text_file.read() + text_file.close() + json_content = json.loads(data) + issue_tracker = json_content["issueTracker"] # JSON is in Codemeta format + + #len(json_content["citation"]) + #codemeta category citation is now referencePublication + assert issue_tracker == 'https://github.com/dgarijo/Widoco/issues' and len(json_content["referencePublication"]) > 0 and \ + len(json_content["name"]) > 0 and len(json_content["identifier"]) > 0 and \ + len(json_content["description"]) > 0 and len(json_content["readme"]) > 0 and \ + len(json_content["buildInstructions"]) > 0 and \ + len(json_content["softwareRequirements"]) > 0 and len(json_content["programmingLanguage"]) > 0 and \ + len(json_content["keywords"]) > 0 and len(json_content["logo"]) > 0 and \ + len(json_content["license"]) > 0 and len(json_content["dateCreated"]) > 0 + + os.remove(test_data_path + "test-417.json-ld") @classmethod def tearDownClass(cls): """delete temp file JSON just if all the test pass""" - if os.path.exists(cls.json_file): # Verifica que el archivo exista + if os.path.exists(cls.json_file): try: os.remove(cls.json_file) - print(f"Deleted {cls.json_file}") # Mensaje para confirmar la eliminación + print(f"Deleted {cls.json_file}") except Exception as e: - print(f"Failed to delete {cls.json_file}: {e}") # Captura errores de eliminación - + print(f"Failed to delete {cls.json_file}: {e}") + if __name__ == "__main__": unittest.main() diff --git a/src/somef_core/test/test_codemeta_parser 2.py b/src/somef_core/test/test_codemeta_parser 2.py new file mode 100644 index 0000000..880cb0f --- /dev/null +++ b/src/somef_core/test/test_codemeta_parser 2.py @@ -0,0 +1,66 @@ +import unittest +import os +import yaml +from pathlib import Path + +from somef_core.parser.codemeta_parser import parse_codemeta_json_file +from somef_core.process_results import Result +from somef_core.utils import constants + +TEST_ROOT = Path(__file__).parent +REPOS_DIR = TEST_ROOT / "test_data" / "repositories" +EXPECT_DIR = TEST_ROOT / "test_data" / "expected" + +class TestCodemetaParser(unittest.TestCase): + + def load_expected(self, repo_name): + """Load expected YAML for a given repo.""" + yaml_path = EXPECT_DIR / f"{repo_name}.yaml" + if not yaml_path.exists(): + self.skipTest(f"No expected YAML for repository '{repo_name}'") + with open(yaml_path, "r", encoding="utf-8") as f: + return yaml.safe_load(f) + + def test_parse_multiple_codemeta_files(self): + for repo_folder in os.listdir(REPOS_DIR): + print(f"################# Testing {repo_folder} #################") + repo_path = REPOS_DIR / repo_folder + codemeta_path = repo_path / "codemeta.json" + if not codemeta_path.is_file(): + continue + + expected = self.load_expected(repo_folder) + result = Result() + metadata_result = parse_codemeta_json_file( + str(codemeta_path), + result, + "https://example.org/codemeta.json" + ) + + with self.subTest(repo=repo_folder): + # In order for us to check every test, we need every file in "expected" directory to be of .yaml, + # and make sure the name is the same as the repo folder + print(f"################# Processing expectation of {repo_folder} #################") + for cat_name, expected_val in expected.items(): + cat_const = getattr(constants, cat_name) + actual_list = metadata_result.results.get(cat_const, []) + self.assertTrue( + actual_list, + f"[{repo_folder}] No results for {cat_name}" + ) + + first = actual_list[0]["result"] + if isinstance(expected_val, dict): + for key, val in expected_val.items(): + self.assertEqual( + first.get(key), val, + f"[{repo_folder}] Mismatch in {cat_name}.{key}" + ) + else: + self.assertEqual( + first.get("value"), expected_val, + f"[{repo_folder}] Mismatch in {cat_name}" + ) + +if __name__ == "__main__": + unittest.main() diff --git a/src/somef_core/test/test_codemeta_parser.py b/src/somef_core/test/test_codemeta_parser.py new file mode 100644 index 0000000..880cb0f --- /dev/null +++ b/src/somef_core/test/test_codemeta_parser.py @@ -0,0 +1,66 @@ +import unittest +import os +import yaml +from pathlib import Path + +from somef_core.parser.codemeta_parser import parse_codemeta_json_file +from somef_core.process_results import Result +from somef_core.utils import constants + +TEST_ROOT = Path(__file__).parent +REPOS_DIR = TEST_ROOT / "test_data" / "repositories" +EXPECT_DIR = TEST_ROOT / "test_data" / "expected" + +class TestCodemetaParser(unittest.TestCase): + + def load_expected(self, repo_name): + """Load expected YAML for a given repo.""" + yaml_path = EXPECT_DIR / f"{repo_name}.yaml" + if not yaml_path.exists(): + self.skipTest(f"No expected YAML for repository '{repo_name}'") + with open(yaml_path, "r", encoding="utf-8") as f: + return yaml.safe_load(f) + + def test_parse_multiple_codemeta_files(self): + for repo_folder in os.listdir(REPOS_DIR): + print(f"################# Testing {repo_folder} #################") + repo_path = REPOS_DIR / repo_folder + codemeta_path = repo_path / "codemeta.json" + if not codemeta_path.is_file(): + continue + + expected = self.load_expected(repo_folder) + result = Result() + metadata_result = parse_codemeta_json_file( + str(codemeta_path), + result, + "https://example.org/codemeta.json" + ) + + with self.subTest(repo=repo_folder): + # In order for us to check every test, we need every file in "expected" directory to be of .yaml, + # and make sure the name is the same as the repo folder + print(f"################# Processing expectation of {repo_folder} #################") + for cat_name, expected_val in expected.items(): + cat_const = getattr(constants, cat_name) + actual_list = metadata_result.results.get(cat_const, []) + self.assertTrue( + actual_list, + f"[{repo_folder}] No results for {cat_name}" + ) + + first = actual_list[0]["result"] + if isinstance(expected_val, dict): + for key, val in expected_val.items(): + self.assertEqual( + first.get(key), val, + f"[{repo_folder}] Mismatch in {cat_name}.{key}" + ) + else: + self.assertEqual( + first.get("value"), expected_val, + f"[{repo_folder}] Mismatch in {cat_name}" + ) + +if __name__ == "__main__": + unittest.main() diff --git a/src/somef_core/test/test_composer_parser 2.py b/src/somef_core/test/test_composer_parser 2.py new file mode 100644 index 0000000..e525e58 --- /dev/null +++ b/src/somef_core/test/test_composer_parser 2.py @@ -0,0 +1,59 @@ +import unittest +import os +import sys +import json +from pathlib import Path +from somef_core.process_results import Result +from somef_core.parser.composer_parser import parse_composer_json +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestComposerParser(unittest.TestCase): + def test_parse_composer_json(self): + composer_path = test_data_repositories + os.path.sep+ "composer"+ os.path.sep+ "composer.json" + result = Result() + + metadata_result = parse_composer_json(composer_path, result, "https://example.org/composer.json") + + self.assertIn(constants.CAT_PACKAGE_ID, metadata_result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "composer/composer") + + self.assertIn(constants.CAT_DESCRIPTION, metadata_result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.") + + self.assertIn(constants.CAT_LICENSE, metadata_result.results) + license_value = result.results[constants.CAT_LICENSE][0]["result"]["value"] + self.assertEqual(license_value, "MIT") + + self.assertIn(constants.CAT_REQUIREMENTS, metadata_result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + dep_names = [d["result"]["name"] for d in dependencies] + self.assertIn("php", dep_names) + + + def test_parse_composer_json_2(self): + composer_path = test_data_repositories + os.path.sep+ "codecov"+ os.path.sep+ "composer.json" + result = Result() + + metadata_result = parse_composer_json(composer_path, result, "https://example.org/composer_2.json") + + self.assertIn(constants.CAT_DESCRIPTION, metadata_result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "Codecov Example PHP") + + self.assertIn(constants.CAT_PACKAGE_ID, metadata_result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "codecov/codecov-php") + + self.assertIn(constants.CAT_REQUIREMENTS, metadata_result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual(dependencies[0]["result"]["name"], "php") + self.assertEqual(dependencies[0]["result"]["dependency_type"], "runtime") + self.assertEqual(dependencies[1]["result"]["dependency_type"], "dev") + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_composer_parser.py b/src/somef_core/test/test_composer_parser.py new file mode 100644 index 0000000..e525e58 --- /dev/null +++ b/src/somef_core/test/test_composer_parser.py @@ -0,0 +1,59 @@ +import unittest +import os +import sys +import json +from pathlib import Path +from somef_core.process_results import Result +from somef_core.parser.composer_parser import parse_composer_json +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestComposerParser(unittest.TestCase): + def test_parse_composer_json(self): + composer_path = test_data_repositories + os.path.sep+ "composer"+ os.path.sep+ "composer.json" + result = Result() + + metadata_result = parse_composer_json(composer_path, result, "https://example.org/composer.json") + + self.assertIn(constants.CAT_PACKAGE_ID, metadata_result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "composer/composer") + + self.assertIn(constants.CAT_DESCRIPTION, metadata_result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.") + + self.assertIn(constants.CAT_LICENSE, metadata_result.results) + license_value = result.results[constants.CAT_LICENSE][0]["result"]["value"] + self.assertEqual(license_value, "MIT") + + self.assertIn(constants.CAT_REQUIREMENTS, metadata_result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + dep_names = [d["result"]["name"] for d in dependencies] + self.assertIn("php", dep_names) + + + def test_parse_composer_json_2(self): + composer_path = test_data_repositories + os.path.sep+ "codecov"+ os.path.sep+ "composer.json" + result = Result() + + metadata_result = parse_composer_json(composer_path, result, "https://example.org/composer_2.json") + + self.assertIn(constants.CAT_DESCRIPTION, metadata_result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "Codecov Example PHP") + + self.assertIn(constants.CAT_PACKAGE_ID, metadata_result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "codecov/codecov-php") + + self.assertIn(constants.CAT_REQUIREMENTS, metadata_result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual(dependencies[0]["result"]["name"], "php") + self.assertEqual(dependencies[0]["result"]["dependency_type"], "runtime") + self.assertEqual(dependencies[1]["result"]["dependency_type"], "dev") + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_configuration.py b/src/somef_core/test/test_configuration.py index c8bf9f9..6097a3f 100644 --- a/src/somef_core/test/test_configuration.py +++ b/src/somef_core/test/test_configuration.py @@ -1,6 +1,6 @@ import unittest from ..configuration import get_configuration_file -from somef.utils import constants +from somef_core.utils import constants class TestConfiguration(unittest.TestCase): diff --git a/src/somef_core/test/test_data/README-EUVpy 2.md b/src/somef_core/test/test_data/README-EUVpy 2.md new file mode 100644 index 0000000..26c2756 --- /dev/null +++ b/src/somef_core/test/test_data/README-EUVpy 2.md @@ -0,0 +1,166 @@ + + + +[_(EUV imagery of the solar disk, taken by NASA SDO)_](https://www.nist.gov/image/1280px-sun-august12010jpg) + +# Overview +`EUVpy` is a Python module that contains the NEUVAC empirical model of solar EUV irradiance for use primarily in thermosphere-ionosphere models. +Conceptual development was carried out by Dr. Aaron J. Ridley and analysis and contributions were made by Dr. Daniel A. Brandt and Dr. Joseph Paki. + +`EUVpy` also contains code for running, comparing, and analyzing the performance of NEUVAC in comparison to other +empirical models such as EUVAC, HEUVAC, HFG, and FISM2. As such, the package includes access to EUVAC, HEUVAC, and HFG, +and allows the user to download the F10.7 index at will. + +# Installation + +You can obtain `EUVpy` with a simple git clone command. In the terminal, execute the following command: + +> git clone https://github.com/DanBrandt/EUVpy.git + +The EUVpy package provides access to the HEUVAC model, which is written in Fortran and requires gfortran to be installed. To +install gfortran (if you don't already have it), open a terminal and execute the following command: + +> sudo apt-get install gfortran + +Now, enter into the package folder and run the following command in order to compile the Fortran code that HEUVAC +alone depends upon: + +> cd EUVpy\ +> . install_heuvac.sh + +If this step gives you trouble, try executing the following code **first**, and then retry the above commands. + +> git submodule update --init --recursive --remote + +After HEUVAC is compiled once, you should never have to compile it again. + +Now you are in a position to install the rest of the EUVpy package. Before doing this, you will first want to initialize a Python virtual environment. + +> cd ~/.virtualenvs\ +> python**3.x** -m venv myVenv\ +> pip install --upgrade pip\ +> pip install wheel\ +> source myVenv/bin/activate + +Above, 'python**3.x**' refers to whatever version of Python 3 you have installed. EUVpy works with any version of Python 3. +You may now use one of two ways to install EUVpy. You can install from the cloned repo directly, or you can install from PyPI. + +## Installing from the Cloned Repository + +Navigate back to the package folder: + +> cd\ +> cd myDirectory/EUVpy + +After this is done, simply execute the following command: + +> pip install . + +## Installing from PyPI + +A simpler way to install also involves just entering the following in the terminal: + +> pip install EUVpy + +**Note:** If you choose this route, you'll have to install HEUVAC differently than described above. You will have to +navigate the directory containing the HEUVAC files, and execute the following command, as follows: + +> cd src/EUVpy/empiricalModels/models/HEUVAC/srcHEUVAC +> . compile.sh + +You can then return to the top package directory. This should only have to be done once. +This approach will be replaced with a user-friendly console script in the next release of this package. + +### Unit Testing + +**Note: this section only applies if you installed from the cloned repo.** + +Just to make sure everything installed correctly, while in the package folder, run the following command in the terminal. + +> pytest + +If all of the tests pass, you should be good to go! If you find an issue at this step (or any other) please don't hesitate +to reach out! + +# Usage +EUVpy contains modules for **4** different EUV irradiance models. These models include: +* NEUVAC +* EUVAC +* HEUVAC +* HFG (SOLOMON) + +We note that SOLOMON in the literature can either refer to the empirical model between F10.7 and 81 day-averaged F10.7 +centered on the current day (hereafter F10.7A) and EUV irradiance in 22 overlapping bands as described by Solomon and +Qian 2005, or it can refer to _any_ EUV irradiance data summed into those 22 overlapping bins (referred to as the STAN +BANDS). In this package, SOLOMON only refers to the former, though functionality does exist to run all other models in +the STAN BANDS. + +## Finding your way around + +There are few folders in this package: +* **empiricalModels**: Contains code and data for EUVAC, HEUVAC, and SOLOMON, as well as FISM: +* **experiments**: Contains code and figures related to the publication associated with NEUVAC. In this folder, the file +_fitNeuvac.py_ s used for actually performing the NEUVAC fits between F10.7, F10.7A, and FISM2, while _uncNeuvac.py_ +contains code for computing the correlation matrix used to enable running NEUVAC ensembles, as well as generating plots +of the squared difference between NEUVAC and FISM2 in different bands. +* **NEUVAC**: Contains the code for running NEUVAC. +* **solarIndices**: Contains F10.7 solar index data, from both OMNIWeb and Penticton. +* **tools**: Contains code for miscellaneous helper functions. In this folder appears the following: + * _EUV_: Contains numerous functions within fism2_process.py for reading in and rebinning FISM2 data. + * _processIndices.py_: Contains functions for reading in, downloading, and cleaning OMNIWeb data. + * _processIrradiances.py_: Contains functions for reading in data from TIMED/SEE, SDO/EVE, and FISM. + * _spectralAnalysis.py_: Contains functions for converting between solar spectral irradiance and solar spectral flux. + * _toolbox.py_: Contains miscellaneous helper functions that mainly focus on directory management, loading and saving data, statistics, and fitting. + +Each of the models in EUVpy requires F10.7 as an input. To grab F10.7 between any two dates, simply do the following: + +> from EUVpy.tools import processIndices +> +> f107times, f107, f107a, f107b = processIndices.getCLSF107('YYYY-MM-DD', 'YYYY-MM-DD', truncate=False) + +To import any of the models, simply do as follows: + +NEUVAC +> from EUVpy.NEUVAC import neuvac +> +> neuvacIrr, _, _, _ = neuvac.neuvacEUV(f107, f107b, bands='EUVAC') + +EUVAC +> from EUVpy.empiricalModels.models.EUVAC import euvac +> +> euvacFlux, euvacIrr, _, _, _ = euvac.euvac(f107, f107a) + +HEUVAC +> from EUVpy.empiricalModels.models.HEUVAC import heuvac +> +> heuvac_wav, heuvacFlux, heuvacIrr, _, _, _ = heuvac.heuvac(f107, f107a, torr=True) + +SOLOMON +> from EUVpy.empiricalModels.models.SOLOMON import solomon +> +> solomonFluxHFG, solomonIrrHFG = SOLOMON.solomon.solomon(f107, f107a, model='HFG') +> +> solomonFluxEUVAC, solomonIrrEUVAC = SOLOMON.solomon.solomon(f107, f107a, model='EUVAC') + +# Examples + +There is a [Python notebook](https://github.com/DanBrandt/EUVpy/blob/main/examples/euvpy_examples.ipynb) you can walk through in order to get familiar with the basic functionality of EUVpy. + +We encourage you to peruse [more examples](https://github.com/DanBrandt/EUVpy/blob/main/docs/source/examples.rst) in the documentation for guidelines on how to run each of the models. + +Due to the unique construction of NEUVAC, at present, we only recommend running ensembles for NEUVAC, and not any of the +other models. + +# Code of Conduct +In using this code, depending on the module used, proper citations should be given to the original authors responsible +for developing each model or dataset: + +NEUVAC: [Brandt and Ridley, 2024](https://agupubs.onlinelibrary.wiley.com/doi/pdfdirect/10.1029/2024SW004043) + +EUVAC: [Richards, et al. 1994](https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/94ja00518) + +HEUVAC [Richards, et al. 2006](https://www.sciencedirect.com/science/article/pii/S0273117705008288?casa_token=zEhwbyXrC8MAAAAA:qHFmKe0ZDE4gMsAX9qAHESvPyoEDFLBlhHuLaEsIwYFykhFXN79--XttCW-QDg1sA4wgD54ysFc) + +SOLOMON [Solomon and Qian, 2005](https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2005JA011160) + +FISM2: [Chamberlin, et al. 2020](https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2020SW002588) diff --git a/src/somef_core/test/test_data/README-EUVpy.md b/src/somef_core/test/test_data/README-EUVpy.md new file mode 100644 index 0000000..26c2756 --- /dev/null +++ b/src/somef_core/test/test_data/README-EUVpy.md @@ -0,0 +1,166 @@ + + + +[_(EUV imagery of the solar disk, taken by NASA SDO)_](https://www.nist.gov/image/1280px-sun-august12010jpg) + +# Overview +`EUVpy` is a Python module that contains the NEUVAC empirical model of solar EUV irradiance for use primarily in thermosphere-ionosphere models. +Conceptual development was carried out by Dr. Aaron J. Ridley and analysis and contributions were made by Dr. Daniel A. Brandt and Dr. Joseph Paki. + +`EUVpy` also contains code for running, comparing, and analyzing the performance of NEUVAC in comparison to other +empirical models such as EUVAC, HEUVAC, HFG, and FISM2. As such, the package includes access to EUVAC, HEUVAC, and HFG, +and allows the user to download the F10.7 index at will. + +# Installation + +You can obtain `EUVpy` with a simple git clone command. In the terminal, execute the following command: + +> git clone https://github.com/DanBrandt/EUVpy.git + +The EUVpy package provides access to the HEUVAC model, which is written in Fortran and requires gfortran to be installed. To +install gfortran (if you don't already have it), open a terminal and execute the following command: + +> sudo apt-get install gfortran + +Now, enter into the package folder and run the following command in order to compile the Fortran code that HEUVAC +alone depends upon: + +> cd EUVpy\ +> . install_heuvac.sh + +If this step gives you trouble, try executing the following code **first**, and then retry the above commands. + +> git submodule update --init --recursive --remote + +After HEUVAC is compiled once, you should never have to compile it again. + +Now you are in a position to install the rest of the EUVpy package. Before doing this, you will first want to initialize a Python virtual environment. + +> cd ~/.virtualenvs\ +> python**3.x** -m venv myVenv\ +> pip install --upgrade pip\ +> pip install wheel\ +> source myVenv/bin/activate + +Above, 'python**3.x**' refers to whatever version of Python 3 you have installed. EUVpy works with any version of Python 3. +You may now use one of two ways to install EUVpy. You can install from the cloned repo directly, or you can install from PyPI. + +## Installing from the Cloned Repository + +Navigate back to the package folder: + +> cd\ +> cd myDirectory/EUVpy + +After this is done, simply execute the following command: + +> pip install . + +## Installing from PyPI + +A simpler way to install also involves just entering the following in the terminal: + +> pip install EUVpy + +**Note:** If you choose this route, you'll have to install HEUVAC differently than described above. You will have to +navigate the directory containing the HEUVAC files, and execute the following command, as follows: + +> cd src/EUVpy/empiricalModels/models/HEUVAC/srcHEUVAC +> . compile.sh + +You can then return to the top package directory. This should only have to be done once. +This approach will be replaced with a user-friendly console script in the next release of this package. + +### Unit Testing + +**Note: this section only applies if you installed from the cloned repo.** + +Just to make sure everything installed correctly, while in the package folder, run the following command in the terminal. + +> pytest + +If all of the tests pass, you should be good to go! If you find an issue at this step (or any other) please don't hesitate +to reach out! + +# Usage +EUVpy contains modules for **4** different EUV irradiance models. These models include: +* NEUVAC +* EUVAC +* HEUVAC +* HFG (SOLOMON) + +We note that SOLOMON in the literature can either refer to the empirical model between F10.7 and 81 day-averaged F10.7 +centered on the current day (hereafter F10.7A) and EUV irradiance in 22 overlapping bands as described by Solomon and +Qian 2005, or it can refer to _any_ EUV irradiance data summed into those 22 overlapping bins (referred to as the STAN +BANDS). In this package, SOLOMON only refers to the former, though functionality does exist to run all other models in +the STAN BANDS. + +## Finding your way around + +There are few folders in this package: +* **empiricalModels**: Contains code and data for EUVAC, HEUVAC, and SOLOMON, as well as FISM: +* **experiments**: Contains code and figures related to the publication associated with NEUVAC. In this folder, the file +_fitNeuvac.py_ s used for actually performing the NEUVAC fits between F10.7, F10.7A, and FISM2, while _uncNeuvac.py_ +contains code for computing the correlation matrix used to enable running NEUVAC ensembles, as well as generating plots +of the squared difference between NEUVAC and FISM2 in different bands. +* **NEUVAC**: Contains the code for running NEUVAC. +* **solarIndices**: Contains F10.7 solar index data, from both OMNIWeb and Penticton. +* **tools**: Contains code for miscellaneous helper functions. In this folder appears the following: + * _EUV_: Contains numerous functions within fism2_process.py for reading in and rebinning FISM2 data. + * _processIndices.py_: Contains functions for reading in, downloading, and cleaning OMNIWeb data. + * _processIrradiances.py_: Contains functions for reading in data from TIMED/SEE, SDO/EVE, and FISM. + * _spectralAnalysis.py_: Contains functions for converting between solar spectral irradiance and solar spectral flux. + * _toolbox.py_: Contains miscellaneous helper functions that mainly focus on directory management, loading and saving data, statistics, and fitting. + +Each of the models in EUVpy requires F10.7 as an input. To grab F10.7 between any two dates, simply do the following: + +> from EUVpy.tools import processIndices +> +> f107times, f107, f107a, f107b = processIndices.getCLSF107('YYYY-MM-DD', 'YYYY-MM-DD', truncate=False) + +To import any of the models, simply do as follows: + +NEUVAC +> from EUVpy.NEUVAC import neuvac +> +> neuvacIrr, _, _, _ = neuvac.neuvacEUV(f107, f107b, bands='EUVAC') + +EUVAC +> from EUVpy.empiricalModels.models.EUVAC import euvac +> +> euvacFlux, euvacIrr, _, _, _ = euvac.euvac(f107, f107a) + +HEUVAC +> from EUVpy.empiricalModels.models.HEUVAC import heuvac +> +> heuvac_wav, heuvacFlux, heuvacIrr, _, _, _ = heuvac.heuvac(f107, f107a, torr=True) + +SOLOMON +> from EUVpy.empiricalModels.models.SOLOMON import solomon +> +> solomonFluxHFG, solomonIrrHFG = SOLOMON.solomon.solomon(f107, f107a, model='HFG') +> +> solomonFluxEUVAC, solomonIrrEUVAC = SOLOMON.solomon.solomon(f107, f107a, model='EUVAC') + +# Examples + +There is a [Python notebook](https://github.com/DanBrandt/EUVpy/blob/main/examples/euvpy_examples.ipynb) you can walk through in order to get familiar with the basic functionality of EUVpy. + +We encourage you to peruse [more examples](https://github.com/DanBrandt/EUVpy/blob/main/docs/source/examples.rst) in the documentation for guidelines on how to run each of the models. + +Due to the unique construction of NEUVAC, at present, we only recommend running ensembles for NEUVAC, and not any of the +other models. + +# Code of Conduct +In using this code, depending on the module used, proper citations should be given to the original authors responsible +for developing each model or dataset: + +NEUVAC: [Brandt and Ridley, 2024](https://agupubs.onlinelibrary.wiley.com/doi/pdfdirect/10.1029/2024SW004043) + +EUVAC: [Richards, et al. 1994](https://agupubs.onlinelibrary.wiley.com/doi/abs/10.1029/94ja00518) + +HEUVAC [Richards, et al. 2006](https://www.sciencedirect.com/science/article/pii/S0273117705008288?casa_token=zEhwbyXrC8MAAAAA:qHFmKe0ZDE4gMsAX9qAHESvPyoEDFLBlhHuLaEsIwYFykhFXN79--XttCW-QDg1sA4wgD54ysFc) + +SOLOMON [Solomon and Qian, 2005](https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2005JA011160) + +FISM2: [Chamberlin, et al. 2020](https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2020SW002588) diff --git a/src/somef_core/test/test_data/README-citation-file-format 2.md b/src/somef_core/test/test_data/README-citation-file-format 2.md new file mode 100644 index 0000000..1f5e486 --- /dev/null +++ b/src/somef_core/test/test_data/README-citation-file-format 2.md @@ -0,0 +1,158 @@ +# Citation File Format + +[![Build Status](https://github.com/citation-file-format/citation-file-format/workflows/testing/badge.svg?branch=main)](https://github.com/citation-file-format/citation-file-format/actions/workflows/testing.yml?query=branch%3Amain) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1003149.svg)](https://doi.org/10.5281/zenodo.1003149) +[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) +[![Project homepage](https://img.shields.io/badge/Project%20homepage-citation--file--format.github.io-ff0080)](https://citation-file-format.github.io) + +The Citation File Format lets you provide citation metadata for software or datasets +in plaintext files that are easy to read by both humans and machines. + +## Structure + +You can specify citation metadata for your software (or dataset) in a file named `CITATION.cff`. +This is what a typical `CITATION.cff` file may look like for research software: + +```yaml +cff-version: 1.2.0 +message: If you use this software, please cite it using these metadata. +title: My Research Software +abstract: This is my awesome research software. It does many things. +authors: + - family-names: Druskat + given-names: Stephan + orcid: "https://orcid.org/1234-5678-9101-1121" + - name: "The Research Software project" +version: 0.11.2 +date-released: "2021-07-18" +identifiers: + - description: This is the collection of archived snapshots of all versions of My Research Software + type: doi + value: "10.5281/zenodo.123456" + - description: This is the archived snapshot of version 0.11.2 of My Research Software + type: doi + value: "10.5281/zenodo.123457" +license: Apache-2.0 +repository-code: "https://github.com/citation-file-format/my-research-software" +``` + +In addition, the Citation File Format allows you to + +- provide references to works that your software or dataset builds on ([see here for more info](schema-guide.md#referencing-other-work)); +- ask people to cite a different, related work instead of the software or dataset itself ([see here for more info](schema-guide.md#credit-redirection)). + +## Format specifications :books: + +**You can find the complete format specifications in the [Guide to the Citation File Format schema](schema-guide.md).** + +## Why should I add a `CITATION.cff` file to my repository? :bulb: + +When you do this, great things may happen: + +1. Users of your software can easily cite it using the metadata from `CITATION.cff`! +2. If your repository is hosted on GitHub, they will [show the citation information in the sidebar](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files), which makes it easy for visitors to cite your software or dataset correctly. +3. When you publish your software on Zenodo via the [GitHub-Zenodo integration](https://docs.github.com/en/repositories/archiving-a-github-repository/referencing-and-citing-content), they will use the metadata from your `CITATION.cff` file. +4. People can import the correct reference to your software into the [Zotero](https://www.zotero.org) reference manager via a [browser plugin](https://www.zotero.org/download/). + +## Creation :heavy_plus_sign: + +To create a `CITATION.cff` file, you can + +- use the [**cffinit** website](https://citation-file-format.github.io/cff-initializer-javascript/#/), +- copy and paste the [example snippet](#structure), and adapt it to your needs, or +- create a new file called `CITATION.cff` using the *Add file* button on GitHub, and use the template they provide. + +## Validation :heavy_check_mark: + +You can validate your `CITATION.cff` file on the command line with the [`cffconvert` Python package](https://pypi.org/project/cffconvert/): + +```shell +# Install cffconvert with pip in user space +python3 -m pip install --user cffconvert + +# Validate your CFF file +cffconvert --validate +``` + +If you get a Traceback with error messages, look for the relevant validation error and fix it. +If the output is very long, it may help if you search it for lines starting with `jsonschema.exceptions.ValidationError`. + +If you prefer to use Docker, you can use the [`cffconvert` Docker image](https://hub.docker.com/r/citationcff/cffconvert): + +```bash +cd +docker run --rm -v ${PWD}:/app citationcff/cffconvert --validate +``` + + + +## Tools to work with `CITATION.cff` files :wrench: + +There is tooling available to work with `CITATION.cff` files to do different things: +create new files, edit existing files, validate existing files, convert files from the Citation File Format into another format. +The following table gives an overview of the tools that we know about. If there is a tool missing from this table, please [open a new issue](https://github.com/citation-file-format/citation-file-format/issues/new/choose) and let us know. + +| | Creation | Editing/Updating | Validation | Conversion | +| -------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Command line | | | • [cffconvert](#validation-heavy_check_mark) | • [cffconvert](https://pypi.org/project/cffconvert/)
• [bibtex-to-cff](https://github.com/monperrus/bibtexbrowser/)
• [cff-from-621](https://pypi.org/project/cff-from-621/)
• [openCARP-CI](https://git.opencarp.org/openCARP/openCARP-CI/-/tree/master/#create_cff) | +| GitHub Actions | | | [cff-validator](https://github.com/marketplace/actions/cff-validator) | • [cffconvert](https://github.com/marketplace/actions/cffconvert)
• [codemeta2cff](https://github.com/caltechlibrary/codemeta2cff) | +| GitHub Bot | | | [#238](https://github.com/citation-file-format/citation-file-format/issues/238) | | +| Docker | | | [cffconvert Docker image](#validation-heavy_check_mark) | [cffconvert Docker image](https://hub.docker.com/r/citationcff/cffconvert) | +| Go | | | | • [datatools/codemeta2cff](https://github.com/caltechlibrary/datatools/) | +| Haskell | | • [cffreference](https://github.com/kevinmatthes/cffreference) | | | +| Java | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | +| JavaScript | | | | • [Citation.js](https://citation.js.org/) [plugin](https://www.npmjs.com/package/@citation-js/plugin-software-formats) | +| Julia | | | • [Bibliography.jl](https://github.com/Humans-of-Julia/Bibliography.jl) | • [Bibliography.jl](https://github.com/Humans-of-Julia/Bibliography.jl) | +| PHP | | | | • [bibtex-to-cff](https://github.com/monperrus/bibtexbrowser/) | +| Python | | • [cff2toml](https://github.com/willynilly/cff2toml)
• [doi2cff](https://github.com/citation-file-format/doi2cff)
• [updateCitation](https://github.com/hunterhogan/updateCitation) | • [cffconvert](#validation-heavy_check_mark) | • [cff-from-621](https://pypi.org/project/cff-from-621/)
• [cff2toml](https://github.com/willynilly/cff2toml)
• [cffconvert](https://github.com/citation-file-format/cff-converter-python)
• [doi2cff](https://github.com/citation-file-format/doi2cff)
• [openCARP-CI](https://git.opencarp.org/openCARP/openCARP-CI/-/tree/master/#create_cff)
• [py_bibtex_to_cff_converter](https://github.com/vdplasthijs/py_bibtex_to_cff_converter) | +| R | | | • [cffr](https://CRAN.R-project.org/package=cffr) | • [citation](https://cran.r-project.org/web/packages/citation/)
• [r2cff](https://github.com/ocbe-uio/RCFF)
• [handlr](https://github.com/ropensci/handlr)
• [cffr](https://CRAN.R-project.org/package=cffr) | +| Ruby | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | +| Rust | • [Aeruginous](https://github.com/kevinmatthes/aeruginous-rs) | • [Aeruginous](https://github.com/kevinmatthes/aeruginous-rs) | | • [citeworks](https://github.com/passcod/citeworks) | +| TypeScript | | | | [#28](https://github.com/citation-file-format/citation-file-format/issues/28#issuecomment-892105342) | +| Website | • [cffinit](https://citation-file-format.github.io/cff-initializer-javascript/) | | | | + +## Maintainers :nerd_face: + +The Citation File Format schema is maintained by + +- Stephan Druskat ([@sdruskat](https://github.com/sdruskat/)) +- Jurriaan H. Spaaks ([@jspaaks](https://github.com/jspaaks/)) + +## Contributing :handshake: + +The Citation File Format is a collaborative project and we welcome suggestions and contributions. We hope one of the invitations below works for you, but if not, please let us know! + +:running: **I'm busy, I only have 1 minute** +- Tell a friend about the Citation File Format, or tweet about it! +- Give the project a star :star:! + +:hourglass_flowing_sand: **I've got 10 minutes - tell me what I should do** +- Create a `CITATION.cff` file for your repository. +- Suggest ideas for how you would like to use the Citation File Format, or for an improvement to the format or its tooling. +- If you know how to validate `CITATION.cff` files, help someone with a validation problem and look at the [issues labeled ![GitHub labels](https://img.shields.io/github/labels/citation-file-format/citation-file-format/validation)](https://github.com/citation-file-format/citation-file-format/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Avalidation) + +:computer: **I've got a few hours to work on this** +- Help create tooling for the community by looking at the [issues labeled ![GitHub labels](https://img.shields.io/github/labels/citation-file-format/citation-file-format/tooling)](https://github.com/citation-file-format/citation-file-format/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Atooling) + +:tada: **I want to help grow the community** +- Write a blog post or news item for your own community. +- Organise a hack event or workshop to help others use or improve the Citation File Format. + +Please read the more detailed [contributing guidelines](CONTRIBUTING.md) and [open a GitHub issue](https://github.com/citation-file-format/citation-file-format/issues) to suggest a new idea or let us know about bugs. Please put up pull requests for changes to the format and schema against the `develop` branch! + +## License :balance_scale: + +Copyright © 2016 - 2023. The Citation File Format Contributors + +This work is licensed under a [Creative Commons Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/legalcode) license. + +## Acknowledgments :pray: + +**We'd like to thank everyone who has contributed to the Citation File Format!** +They are listed in the [`CITATION.cff`](CITATION.cff) file for this repository. Please open an issue if you find that you are missing from the file. + +We gratefully acknowledge support from: + +- The [Institute for Software Technology](https://www.dlr.de/en/sc) of the [German Aerospace Center (DLR)](https://www.dlr.de/en/) +- The [Netherlands eScience Center](https://www.esciencecenter.nl) +- The [Software Sustainability Institute](https://software.ac.uk/) \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-citation-file-format.md b/src/somef_core/test/test_data/README-citation-file-format.md new file mode 100644 index 0000000..1f5e486 --- /dev/null +++ b/src/somef_core/test/test_data/README-citation-file-format.md @@ -0,0 +1,158 @@ +# Citation File Format + +[![Build Status](https://github.com/citation-file-format/citation-file-format/workflows/testing/badge.svg?branch=main)](https://github.com/citation-file-format/citation-file-format/actions/workflows/testing.yml?query=branch%3Amain) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.1003149.svg)](https://doi.org/10.5281/zenodo.1003149) +[![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) +[![Project homepage](https://img.shields.io/badge/Project%20homepage-citation--file--format.github.io-ff0080)](https://citation-file-format.github.io) + +The Citation File Format lets you provide citation metadata for software or datasets +in plaintext files that are easy to read by both humans and machines. + +## Structure + +You can specify citation metadata for your software (or dataset) in a file named `CITATION.cff`. +This is what a typical `CITATION.cff` file may look like for research software: + +```yaml +cff-version: 1.2.0 +message: If you use this software, please cite it using these metadata. +title: My Research Software +abstract: This is my awesome research software. It does many things. +authors: + - family-names: Druskat + given-names: Stephan + orcid: "https://orcid.org/1234-5678-9101-1121" + - name: "The Research Software project" +version: 0.11.2 +date-released: "2021-07-18" +identifiers: + - description: This is the collection of archived snapshots of all versions of My Research Software + type: doi + value: "10.5281/zenodo.123456" + - description: This is the archived snapshot of version 0.11.2 of My Research Software + type: doi + value: "10.5281/zenodo.123457" +license: Apache-2.0 +repository-code: "https://github.com/citation-file-format/my-research-software" +``` + +In addition, the Citation File Format allows you to + +- provide references to works that your software or dataset builds on ([see here for more info](schema-guide.md#referencing-other-work)); +- ask people to cite a different, related work instead of the software or dataset itself ([see here for more info](schema-guide.md#credit-redirection)). + +## Format specifications :books: + +**You can find the complete format specifications in the [Guide to the Citation File Format schema](schema-guide.md).** + +## Why should I add a `CITATION.cff` file to my repository? :bulb: + +When you do this, great things may happen: + +1. Users of your software can easily cite it using the metadata from `CITATION.cff`! +2. If your repository is hosted on GitHub, they will [show the citation information in the sidebar](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files), which makes it easy for visitors to cite your software or dataset correctly. +3. When you publish your software on Zenodo via the [GitHub-Zenodo integration](https://docs.github.com/en/repositories/archiving-a-github-repository/referencing-and-citing-content), they will use the metadata from your `CITATION.cff` file. +4. People can import the correct reference to your software into the [Zotero](https://www.zotero.org) reference manager via a [browser plugin](https://www.zotero.org/download/). + +## Creation :heavy_plus_sign: + +To create a `CITATION.cff` file, you can + +- use the [**cffinit** website](https://citation-file-format.github.io/cff-initializer-javascript/#/), +- copy and paste the [example snippet](#structure), and adapt it to your needs, or +- create a new file called `CITATION.cff` using the *Add file* button on GitHub, and use the template they provide. + +## Validation :heavy_check_mark: + +You can validate your `CITATION.cff` file on the command line with the [`cffconvert` Python package](https://pypi.org/project/cffconvert/): + +```shell +# Install cffconvert with pip in user space +python3 -m pip install --user cffconvert + +# Validate your CFF file +cffconvert --validate +``` + +If you get a Traceback with error messages, look for the relevant validation error and fix it. +If the output is very long, it may help if you search it for lines starting with `jsonschema.exceptions.ValidationError`. + +If you prefer to use Docker, you can use the [`cffconvert` Docker image](https://hub.docker.com/r/citationcff/cffconvert): + +```bash +cd +docker run --rm -v ${PWD}:/app citationcff/cffconvert --validate +``` + + + +## Tools to work with `CITATION.cff` files :wrench: + +There is tooling available to work with `CITATION.cff` files to do different things: +create new files, edit existing files, validate existing files, convert files from the Citation File Format into another format. +The following table gives an overview of the tools that we know about. If there is a tool missing from this table, please [open a new issue](https://github.com/citation-file-format/citation-file-format/issues/new/choose) and let us know. + +| | Creation | Editing/Updating | Validation | Conversion | +| -------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Command line | | | • [cffconvert](#validation-heavy_check_mark) | • [cffconvert](https://pypi.org/project/cffconvert/)
• [bibtex-to-cff](https://github.com/monperrus/bibtexbrowser/)
• [cff-from-621](https://pypi.org/project/cff-from-621/)
• [openCARP-CI](https://git.opencarp.org/openCARP/openCARP-CI/-/tree/master/#create_cff) | +| GitHub Actions | | | [cff-validator](https://github.com/marketplace/actions/cff-validator) | • [cffconvert](https://github.com/marketplace/actions/cffconvert)
• [codemeta2cff](https://github.com/caltechlibrary/codemeta2cff) | +| GitHub Bot | | | [#238](https://github.com/citation-file-format/citation-file-format/issues/238) | | +| Docker | | | [cffconvert Docker image](#validation-heavy_check_mark) | [cffconvert Docker image](https://hub.docker.com/r/citationcff/cffconvert) | +| Go | | | | • [datatools/codemeta2cff](https://github.com/caltechlibrary/datatools/) | +| Haskell | | • [cffreference](https://github.com/kevinmatthes/cffreference) | | | +| Java | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | | • [CFF Maven plugin](https://github.com/hexatomic/cff-maven-plugin) | +| JavaScript | | | | • [Citation.js](https://citation.js.org/) [plugin](https://www.npmjs.com/package/@citation-js/plugin-software-formats) | +| Julia | | | • [Bibliography.jl](https://github.com/Humans-of-Julia/Bibliography.jl) | • [Bibliography.jl](https://github.com/Humans-of-Julia/Bibliography.jl) | +| PHP | | | | • [bibtex-to-cff](https://github.com/monperrus/bibtexbrowser/) | +| Python | | • [cff2toml](https://github.com/willynilly/cff2toml)
• [doi2cff](https://github.com/citation-file-format/doi2cff)
• [updateCitation](https://github.com/hunterhogan/updateCitation) | • [cffconvert](#validation-heavy_check_mark) | • [cff-from-621](https://pypi.org/project/cff-from-621/)
• [cff2toml](https://github.com/willynilly/cff2toml)
• [cffconvert](https://github.com/citation-file-format/cff-converter-python)
• [doi2cff](https://github.com/citation-file-format/doi2cff)
• [openCARP-CI](https://git.opencarp.org/openCARP/openCARP-CI/-/tree/master/#create_cff)
• [py_bibtex_to_cff_converter](https://github.com/vdplasthijs/py_bibtex_to_cff_converter) | +| R | | | • [cffr](https://CRAN.R-project.org/package=cffr) | • [citation](https://cran.r-project.org/web/packages/citation/)
• [r2cff](https://github.com/ocbe-uio/RCFF)
• [handlr](https://github.com/ropensci/handlr)
• [cffr](https://CRAN.R-project.org/package=cffr) | +| Ruby | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | • [ruby-cff](https://github.com/citation-file-format/ruby-cff) | +| Rust | • [Aeruginous](https://github.com/kevinmatthes/aeruginous-rs) | • [Aeruginous](https://github.com/kevinmatthes/aeruginous-rs) | | • [citeworks](https://github.com/passcod/citeworks) | +| TypeScript | | | | [#28](https://github.com/citation-file-format/citation-file-format/issues/28#issuecomment-892105342) | +| Website | • [cffinit](https://citation-file-format.github.io/cff-initializer-javascript/) | | | | + +## Maintainers :nerd_face: + +The Citation File Format schema is maintained by + +- Stephan Druskat ([@sdruskat](https://github.com/sdruskat/)) +- Jurriaan H. Spaaks ([@jspaaks](https://github.com/jspaaks/)) + +## Contributing :handshake: + +The Citation File Format is a collaborative project and we welcome suggestions and contributions. We hope one of the invitations below works for you, but if not, please let us know! + +:running: **I'm busy, I only have 1 minute** +- Tell a friend about the Citation File Format, or tweet about it! +- Give the project a star :star:! + +:hourglass_flowing_sand: **I've got 10 minutes - tell me what I should do** +- Create a `CITATION.cff` file for your repository. +- Suggest ideas for how you would like to use the Citation File Format, or for an improvement to the format or its tooling. +- If you know how to validate `CITATION.cff` files, help someone with a validation problem and look at the [issues labeled ![GitHub labels](https://img.shields.io/github/labels/citation-file-format/citation-file-format/validation)](https://github.com/citation-file-format/citation-file-format/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Avalidation) + +:computer: **I've got a few hours to work on this** +- Help create tooling for the community by looking at the [issues labeled ![GitHub labels](https://img.shields.io/github/labels/citation-file-format/citation-file-format/tooling)](https://github.com/citation-file-format/citation-file-format/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+label%3Atooling) + +:tada: **I want to help grow the community** +- Write a blog post or news item for your own community. +- Organise a hack event or workshop to help others use or improve the Citation File Format. + +Please read the more detailed [contributing guidelines](CONTRIBUTING.md) and [open a GitHub issue](https://github.com/citation-file-format/citation-file-format/issues) to suggest a new idea or let us know about bugs. Please put up pull requests for changes to the format and schema against the `develop` branch! + +## License :balance_scale: + +Copyright © 2016 - 2023. The Citation File Format Contributors + +This work is licensed under a [Creative Commons Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/legalcode) license. + +## Acknowledgments :pray: + +**We'd like to thank everyone who has contributed to the Citation File Format!** +They are listed in the [`CITATION.cff`](CITATION.cff) file for this repository. Please open an issue if you find that you are missing from the file. + +We gratefully acknowledge support from: + +- The [Institute for Software Technology](https://www.dlr.de/en/sc) of the [German Aerospace Center (DLR)](https://www.dlr.de/en/) +- The [Netherlands eScience Center](https://www.esciencecenter.nl) +- The [Software Sustainability Institute](https://software.ac.uk/) \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-componentinstaller 2.md b/src/somef_core/test/test_data/README-componentinstaller 2.md new file mode 100644 index 0000000..376776d --- /dev/null +++ b/src/somef_core/test/test_data/README-componentinstaller 2.md @@ -0,0 +1,139 @@ + +# Component Installer for deploying PySSA +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-blue.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/commit-activity) +[![GitHub issues](https://img.shields.io/github/issues/urban233/ComponentInstaller)](https://GitHub.com/urban233/ComponentInstaller/issues/) +[![GitHub contributors](https://img.shields.io/github/contributors/urban233/ComponentInstaller.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/contributors/) +[![GitHub release](https://img.shields.io/github/v/release/urban233/ComponentInstaller)](https://github.com/urban233/ComponentInstaller/releases/) + +## Contents of this document +* [Description](#Description) +* [Contents of this repository](#Contents-of-this-repository) + * [Sources](#Sources) + * [Documentation](#Documentation) + * [Assets](#Assets) +* [Build](#Build) + * [Windows](#Windows) + * [Source code](#Source-code) +* [Dependencies](#Dependencies) +* [Citation](#Citation) +* [References and useful links](#References-and-useful-links) +* [Acknowledgements](#Acknowledgements) + +## Description +The Component Installer is a software tool designed for use as a component-based installer. +It is capable of addressing a range of deployment contexts that typically necessitate more +intricate configuration than is typically required in other scenarios. +The PySSA Installer serves as a case study demonstrating +the potential utility of the component-based installation methodology. + + +## Contents of this repository +### Sources +The repository comprises four distinct source code units. + +- _src/main/java_ + - The package contains the communicator class, which is utilized for communication with WindowsTasks.exe. +- _src/main/kotlin_ + - The package contains the main source code, including gui and model. +- _WindowsWrapper/WindowsCmdElevator_ + - The package contains the class to elevate a normal cmd shell with admin privileges. +- _WindowsWrapper/WindowsTasks_ + - The package contains the communicator, which facilitates communication with the Kotlin application, as well as a number of useful classes for the management of the MS Windows operating system. + +### Documentation +The "deployment" folder +contains a user guide as PDF file. +This [PDF file](https://github.com/urban233/ComponentInstaller/blob/v1.0.1/deployment/inno_setup/PySSA-Component-Installer-User-Guide.pdf) is also available through the help menu item within the PySSA Component Installer. +The user guide explains the installation and uninstallation of every component +as well as the update procedure for ColabFold and PySSA. Furthermore, +it contains a troubleshooting section for WSL2 and ColabFold. + +### Assets +The "assets" folder contains +all logos including the WSL2, ColabFold and PySSA logo, as well as the PySSA Component Installer logo. +If you are using PySSA Component Installer for your own projects, you are welcome to give credit to PySSA Component Installer by using the logo in your presentations, etc. + +## Build +The Component Installer consists of a Kotlin/Java project and a C# solution with two projects. + +### Windows +To deploy the installer on a Microsoft Windows OS (10 or 11), use the provided +inno setup script as a starting point. +Be aware that the inno setup compiler needs to be pre-installed! + +### Source code +The Kotlin/Java project is a Gradle project. +In order to use the source code for your own software or do your own Component Installer build, +download or clone the repository and open it in a Gradle-supporting IDE (e.g. IntelliJ) +as a Gradle project and execute the build.gradle file. +Gradle will then take care of installing all dependencies. +A Java Development Kit (JDK) of version 17 must also be pre-installed and +set as project JDK / project compiler. + +The C# solution contains the C# project WindowsCmdElevator and WindowsTasks. Both can be compiled to +an .exe file using the provided FolderProfile.pubxml files. + +## Dependencies +**Needs to be pre-installed:** +* Java Development Kit (JDK) version 17 + * [Adoptium Open JDK](https://adoptium.net/temurin/archive/?version=17) (as one possible source of the JDK) +* .NET 8.0 + * [Microsoft .NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + +**Managed by Gradle:** +* Java Native Access (JNA) version 5.8.0 + * [Java Native Access GitHub repository](https://github.com/java-native-access) + * [LGPL, version 2.1 or later, or (from version 4.0 onward) the Apache License, version 2.0](https://github.com/java-native-access/jna?tab=License-1-ov-file) +* JeroMQ version 0.6.0 + * [JeroMQ GitHub repository](https://github.com/zeromq/jeromq) + * Mozilla Public License Version 2.0 + +**Managed by NuGet:** +* NLog version 5.3.2 + * [NLog GitHub repository](https://github.com/NLog/NLog) + * BSD-3-Clause license +* NetMQ version 4.0.1.13 + * [NetMQ GitHub repository](https://github.com/zeromq/netmq/) + * GNU Lesser General Public License 3 + +## Citation +You can cite this software or this repository as it is defined in the CITATION.cff file. + +## References and useful links +**Windows Subsystem for Linux** +* [What is the Windows Subsystem for Linux? (Article)](https://learn.microsoft.com/en-us/windows/wsl/about) +* [How to install Linux on Windows with WSL (Article)](https://learn.microsoft.com/en-us/windows/wsl/install) + +**ZeroMQ** +* [ZeroMQ Homepage](https://zeromq.org/) + * [Java implementation (JeroMQ)](https://github.com/zeromq/jeromq) + * [C# implementation (NetMQ)](https://github.com/zeromq/netmq/) + +## Acknowledgements +**Developers:** +* Martin Urban +* Hannah Kullik + +**End-user testers:** +* Jonas Schaub +* Achim Zielesny + +**Logo:** +* Martin Urban +* Hannah Kullik + +**Initialization, conceptualization, and supervision:** +* Achim Zielesny and Angelika Loidl-Stahlhofen + +**The ComponentInstaller project team would like to thank +the communities behind the open software libraries for their amazing work.** + + diff --git a/src/somef_core/test/test_data/README-componentinstaller.md b/src/somef_core/test/test_data/README-componentinstaller.md new file mode 100644 index 0000000..376776d --- /dev/null +++ b/src/somef_core/test/test_data/README-componentinstaller.md @@ -0,0 +1,139 @@ + +# Component Installer for deploying PySSA +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-blue.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/commit-activity) +[![GitHub issues](https://img.shields.io/github/issues/urban233/ComponentInstaller)](https://GitHub.com/urban233/ComponentInstaller/issues/) +[![GitHub contributors](https://img.shields.io/github/contributors/urban233/ComponentInstaller.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/contributors/) +[![GitHub release](https://img.shields.io/github/v/release/urban233/ComponentInstaller)](https://github.com/urban233/ComponentInstaller/releases/) + +## Contents of this document +* [Description](#Description) +* [Contents of this repository](#Contents-of-this-repository) + * [Sources](#Sources) + * [Documentation](#Documentation) + * [Assets](#Assets) +* [Build](#Build) + * [Windows](#Windows) + * [Source code](#Source-code) +* [Dependencies](#Dependencies) +* [Citation](#Citation) +* [References and useful links](#References-and-useful-links) +* [Acknowledgements](#Acknowledgements) + +## Description +The Component Installer is a software tool designed for use as a component-based installer. +It is capable of addressing a range of deployment contexts that typically necessitate more +intricate configuration than is typically required in other scenarios. +The PySSA Installer serves as a case study demonstrating +the potential utility of the component-based installation methodology. + + +## Contents of this repository +### Sources +The repository comprises four distinct source code units. + +- _src/main/java_ + - The package contains the communicator class, which is utilized for communication with WindowsTasks.exe. +- _src/main/kotlin_ + - The package contains the main source code, including gui and model. +- _WindowsWrapper/WindowsCmdElevator_ + - The package contains the class to elevate a normal cmd shell with admin privileges. +- _WindowsWrapper/WindowsTasks_ + - The package contains the communicator, which facilitates communication with the Kotlin application, as well as a number of useful classes for the management of the MS Windows operating system. + +### Documentation +The "deployment" folder +contains a user guide as PDF file. +This [PDF file](https://github.com/urban233/ComponentInstaller/blob/v1.0.1/deployment/inno_setup/PySSA-Component-Installer-User-Guide.pdf) is also available through the help menu item within the PySSA Component Installer. +The user guide explains the installation and uninstallation of every component +as well as the update procedure for ColabFold and PySSA. Furthermore, +it contains a troubleshooting section for WSL2 and ColabFold. + +### Assets +The "assets" folder contains +all logos including the WSL2, ColabFold and PySSA logo, as well as the PySSA Component Installer logo. +If you are using PySSA Component Installer for your own projects, you are welcome to give credit to PySSA Component Installer by using the logo in your presentations, etc. + +## Build +The Component Installer consists of a Kotlin/Java project and a C# solution with two projects. + +### Windows +To deploy the installer on a Microsoft Windows OS (10 or 11), use the provided +inno setup script as a starting point. +Be aware that the inno setup compiler needs to be pre-installed! + +### Source code +The Kotlin/Java project is a Gradle project. +In order to use the source code for your own software or do your own Component Installer build, +download or clone the repository and open it in a Gradle-supporting IDE (e.g. IntelliJ) +as a Gradle project and execute the build.gradle file. +Gradle will then take care of installing all dependencies. +A Java Development Kit (JDK) of version 17 must also be pre-installed and +set as project JDK / project compiler. + +The C# solution contains the C# project WindowsCmdElevator and WindowsTasks. Both can be compiled to +an .exe file using the provided FolderProfile.pubxml files. + +## Dependencies +**Needs to be pre-installed:** +* Java Development Kit (JDK) version 17 + * [Adoptium Open JDK](https://adoptium.net/temurin/archive/?version=17) (as one possible source of the JDK) +* .NET 8.0 + * [Microsoft .NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + +**Managed by Gradle:** +* Java Native Access (JNA) version 5.8.0 + * [Java Native Access GitHub repository](https://github.com/java-native-access) + * [LGPL, version 2.1 or later, or (from version 4.0 onward) the Apache License, version 2.0](https://github.com/java-native-access/jna?tab=License-1-ov-file) +* JeroMQ version 0.6.0 + * [JeroMQ GitHub repository](https://github.com/zeromq/jeromq) + * Mozilla Public License Version 2.0 + +**Managed by NuGet:** +* NLog version 5.3.2 + * [NLog GitHub repository](https://github.com/NLog/NLog) + * BSD-3-Clause license +* NetMQ version 4.0.1.13 + * [NetMQ GitHub repository](https://github.com/zeromq/netmq/) + * GNU Lesser General Public License 3 + +## Citation +You can cite this software or this repository as it is defined in the CITATION.cff file. + +## References and useful links +**Windows Subsystem for Linux** +* [What is the Windows Subsystem for Linux? (Article)](https://learn.microsoft.com/en-us/windows/wsl/about) +* [How to install Linux on Windows with WSL (Article)](https://learn.microsoft.com/en-us/windows/wsl/install) + +**ZeroMQ** +* [ZeroMQ Homepage](https://zeromq.org/) + * [Java implementation (JeroMQ)](https://github.com/zeromq/jeromq) + * [C# implementation (NetMQ)](https://github.com/zeromq/netmq/) + +## Acknowledgements +**Developers:** +* Martin Urban +* Hannah Kullik + +**End-user testers:** +* Jonas Schaub +* Achim Zielesny + +**Logo:** +* Martin Urban +* Hannah Kullik + +**Initialization, conceptualization, and supervision:** +* Achim Zielesny and Angelika Loidl-Stahlhofen + +**The ComponentInstaller project team would like to thank +the communities behind the open software libraries for their amazing work.** + + diff --git a/src/somef_core/test/test_data/README-menty 2.md b/src/somef_core/test/test_data/README-menty 2.md new file mode 100644 index 0000000..8ac3d87 --- /dev/null +++ b/src/somef_core/test/test_data/README-menty 2.md @@ -0,0 +1,94 @@ +

+ MentPy: A Measurement-Based Quantum computing simulator. +

+ + + +The `mentpy` library is an open-source software for simulations of +measurement-based quantum computing circuits. Currently, this package is in its alpha version and many features are still in development. + +## Installation + +You can install the stable release of `mentpy` from PyPI using: + +```bash +pip install mentpy +``` + +For the latest, potentially unstable version, you can install directly from the source: + +```bash +pip install git+https://github.com/mentpy/mentpy.git +``` + +If you're contributing to `mentpy` and need to install development dependencies, you can do so using: + +```bash +git clone https://github.com/mentpy/mentpy.git +cd mentpy +pip install -e '.[dev]' +``` + +This command installs `mentpy` in editable mode with its additional development dependencies. + +## Usage +To simulate a measurement pattern, you can use the `mp.PatternSimulator`. +```python +import mentpy as mp + +st = mp.templates.grid_cluster(2,4) +ps = mp.PatternSimulator(st) +output = ps(np.random.rand(len(st.outputc))) +``` + +For visualization of circuits, you can use the `mp.draw(st)` function + +![image](https://user-images.githubusercontent.com/52287586/230715389-bf280971-c841-437d-8772-bf59557b0875.png) + +To calculate the lie algebra of a model $G_\theta$, you can use the `mp.utils.calculate_lie_algebra` function + +```python +lie_alg = mp.utils.calculate_lie_algebra(st) +len(lie_alg) +>> 16 +``` + +## Documentation + +The documentation for `mentpy` can be found here. + +## Contributing + +We welcome contributions to `mentpy`! Please see our [contributing guidelines](./CONTRIBUTING.md) for more information. + +## How to cite + +If you use `mentpy` in your research, please cite it as follows: + +``` +@software{mantilla2023mentpy, + title = {{MentPy: A Python package for parametrized MBQC circuits}}, + author = {Mantilla Calderón, Luis}, + year = {2023}, + url = {https://github.com/mentpy/mentpy}, +} +``` \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-menty.md b/src/somef_core/test/test_data/README-menty.md new file mode 100644 index 0000000..8ac3d87 --- /dev/null +++ b/src/somef_core/test/test_data/README-menty.md @@ -0,0 +1,94 @@ +

+ MentPy: A Measurement-Based Quantum computing simulator. +

+ + + +The `mentpy` library is an open-source software for simulations of +measurement-based quantum computing circuits. Currently, this package is in its alpha version and many features are still in development. + +## Installation + +You can install the stable release of `mentpy` from PyPI using: + +```bash +pip install mentpy +``` + +For the latest, potentially unstable version, you can install directly from the source: + +```bash +pip install git+https://github.com/mentpy/mentpy.git +``` + +If you're contributing to `mentpy` and need to install development dependencies, you can do so using: + +```bash +git clone https://github.com/mentpy/mentpy.git +cd mentpy +pip install -e '.[dev]' +``` + +This command installs `mentpy` in editable mode with its additional development dependencies. + +## Usage +To simulate a measurement pattern, you can use the `mp.PatternSimulator`. +```python +import mentpy as mp + +st = mp.templates.grid_cluster(2,4) +ps = mp.PatternSimulator(st) +output = ps(np.random.rand(len(st.outputc))) +``` + +For visualization of circuits, you can use the `mp.draw(st)` function + +![image](https://user-images.githubusercontent.com/52287586/230715389-bf280971-c841-437d-8772-bf59557b0875.png) + +To calculate the lie algebra of a model $G_\theta$, you can use the `mp.utils.calculate_lie_algebra` function + +```python +lie_alg = mp.utils.calculate_lie_algebra(st) +len(lie_alg) +>> 16 +``` + +## Documentation + +The documentation for `mentpy` can be found here. + +## Contributing + +We welcome contributions to `mentpy`! Please see our [contributing guidelines](./CONTRIBUTING.md) for more information. + +## How to cite + +If you use `mentpy` in your research, please cite it as follows: + +``` +@software{mantilla2023mentpy, + title = {{MentPy: A Python package for parametrized MBQC circuits}}, + author = {Mantilla Calderón, Luis}, + year = {2023}, + url = {https://github.com/mentpy/mentpy}, +} +``` \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-sunpy 2.rst b/src/somef_core/test/test_data/README-sunpy 2.rst new file mode 100644 index 0000000..75c6d1a --- /dev/null +++ b/src/somef_core/test/test_data/README-sunpy 2.rst @@ -0,0 +1,115 @@ +********* +``sunpy`` +********* +|SunPy Logo| + ++-----------------------------------+-----------------------------------+-----------------------------------+ +| Release | Development | Community | ++===================================+===================================+===================================+ +| |Latest PyPi Version| | |Python Versions| | |Matrix Chat Room| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |Latest Conda Version| | |Project Status: Active| | |OpenAstronomy Discourse| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |Zenodo - Latest DOI| | |Continuous Integration Status| | |Google Groups Mailing List| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |sunpy stable documentation| | |CodeCov Code Coverage| | |Powered by NumFOCUS| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |sunpy citation| | | |pyOpenSci| | ++-----------------------------------+-----------------------------------+-----------------------------------+ + +.. |SunPy Logo| image:: https://raw.githubusercontent.com/sunpy/sunpy-logo/master/generated/sunpy_logo_landscape.png + :width: 200px +.. |Latest PyPi Version| image:: https://img.shields.io/pypi/v/sunpy.svg + :target: https://pypi.python.org/pypi/sunpy/ +.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/sunpy + :target: https://pypi.python.org/pypi/sunpy/ +.. |Matrix Chat Room| image:: https://img.shields.io/matrix/sunpy:openastronomy.org.svg?colorB=%23FE7900&label=Chat&logo=matrix&server_fqdn=matrix.org + :target: https://app.element.io/#/room/#sunpy:openastronomy.org +.. |Latest Conda Version| image:: https://anaconda.org/conda-forge/sunpy/badges/version.svg + :target: https://anaconda.org/conda-forge/sunpy +.. |Project Status: Active| image:: https://www.repostatus.org/badges/latest/active.svg + :target: https://www.repostatus.org/#active +.. |OpenAstronomy Discourse| image:: https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/try2/original/1X/5e1e3b3cada2d7fbae4734d4bc53999933d71c95.svg + :height: 20px + :target: https://community.openastronomy.org/ +.. |Zenodo - Latest DOI| image:: https://zenodo.org/badge/2165383.svg + :target: https://zenodo.org/badge/latestdoi/2165383 +.. |Continuous Integration Status| image:: https://github.com/sunpy/sunpy/actions/workflows/ci.yml/badge.svg?branch=main + :target: https://github.com/sunpy/sunpy/actions/workflows/ci.yml +.. |Google Groups Mailing List| image:: https://upload.wikimedia.org/wikipedia/commons/2/27/Google_Groups_logo.gif + :height: 20px + :target: https://groups.google.com/g/sunpy +.. |sunpy stable documentation| image:: https://readthedocs.org/projects/sunpy/badge/?version=stable + :target: https://docs.sunpy.org/ +.. |CodeCov Code Coverage| image:: https://codecov.io/gh/sunpy/sunpy/branch/main/graph/badge.svg + :target: https://codecov.io/gh/sunpy/sunpy +.. |Powered by NumFOCUS| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A + :target: https://numfocus.org +.. |sunpy citation| image:: https://img.shields.io/badge/cite-sunpy-orange + :target: https://docs.sunpy.org/en/stable/citation.html +.. |pyOpenSci| image:: https://tinyurl.com/y22nb8up + :target: https://github.com/pyOpenSci/software-submission/issues/147 + +``sunpy`` is a Python software package that provides fundamental tools for accessing, loading and interacting with solar physics data in Python. +It includes an interface for searching and downloading data from multiple data providers, data containers for image and time series data, commonly used solar coordinate frames and associated transformations, as well as other functionality needed for solar data analysis. + +Installation +============ + +We recommended following the `installation guide `__ in the ``sunpy`` documentation. +This will walk you through installing ``sunpy`` and all of its dependencies. + +Usage +===== + +If you are new to ``sunpy``, the best place to start is the `tutorial `__. +the `example gallery `__ also includes a collection of shorter and more specific examples of using ``sunpy``. + +Changes +======= + +See our `changelog `__. for the latest changes in ``sunpy``. + +Getting Help +============ + +For more information or to ask questions about ``sunpy`` or any other SunPy Project package, please check out: + +- `sunpy documentation `__ +- `SunPy Affiliated Packages `__ +- `SunPy Chat`_ +- `SunPy mailing list `__ +- `SunPy Community forum `__ + +Acknowledging or Citing ``sunpy`` +================================= + +If you use ``sunpy`` in your scientific work, we would appreciate your `citing it in your publications `__. +The continued growth and development of ``sunpy`` is dependent on the community being aware of ``sunpy``. + +Contributing +============ + +The SunPy Project is a community-driven open-source project that welcomes any and all contributions. +Whether you are a developer, student, or user, you can help by contributing code, documentation, or community support. + +If you would like to get involved, the `Newcomers Guide`_ guide explains the many different ways to contribute to the SunPy Project and also shows how to get set up with a development workflow. + +Help is always welcome, so come and say hello by joining the `SunPy Chat`_ and look over the `Good First Issues list`_ for the ideal places to start. + +.. _Newcomers Guide: https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html +.. _Good First Issues list: https://github.com/sunpy/sunpy/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Good+First+Issue%22 + +Usage of Generative AI +====================== + +We expect authentic engagement in our community. +Be wary of posting output from Large Language Models or similar generative AI as comments on GitHub or any other platform, as such comments tend to be formulaic and low quality content. +If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach and an improvement to the current state. + +Code of Conduct +=============== + +When you are interacting with the SunPy Community you are asked to follow our `Code of Conduct `__. + +.. _SunPy Chat: https://app.element.io/#/room/#sunpy:openastronomy.org \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-sunpy.rst b/src/somef_core/test/test_data/README-sunpy.rst new file mode 100644 index 0000000..75c6d1a --- /dev/null +++ b/src/somef_core/test/test_data/README-sunpy.rst @@ -0,0 +1,115 @@ +********* +``sunpy`` +********* +|SunPy Logo| + ++-----------------------------------+-----------------------------------+-----------------------------------+ +| Release | Development | Community | ++===================================+===================================+===================================+ +| |Latest PyPi Version| | |Python Versions| | |Matrix Chat Room| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |Latest Conda Version| | |Project Status: Active| | |OpenAstronomy Discourse| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |Zenodo - Latest DOI| | |Continuous Integration Status| | |Google Groups Mailing List| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |sunpy stable documentation| | |CodeCov Code Coverage| | |Powered by NumFOCUS| | ++-----------------------------------+-----------------------------------+-----------------------------------+ +| |sunpy citation| | | |pyOpenSci| | ++-----------------------------------+-----------------------------------+-----------------------------------+ + +.. |SunPy Logo| image:: https://raw.githubusercontent.com/sunpy/sunpy-logo/master/generated/sunpy_logo_landscape.png + :width: 200px +.. |Latest PyPi Version| image:: https://img.shields.io/pypi/v/sunpy.svg + :target: https://pypi.python.org/pypi/sunpy/ +.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/sunpy + :target: https://pypi.python.org/pypi/sunpy/ +.. |Matrix Chat Room| image:: https://img.shields.io/matrix/sunpy:openastronomy.org.svg?colorB=%23FE7900&label=Chat&logo=matrix&server_fqdn=matrix.org + :target: https://app.element.io/#/room/#sunpy:openastronomy.org +.. |Latest Conda Version| image:: https://anaconda.org/conda-forge/sunpy/badges/version.svg + :target: https://anaconda.org/conda-forge/sunpy +.. |Project Status: Active| image:: https://www.repostatus.org/badges/latest/active.svg + :target: https://www.repostatus.org/#active +.. |OpenAstronomy Discourse| image:: https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/try2/original/1X/5e1e3b3cada2d7fbae4734d4bc53999933d71c95.svg + :height: 20px + :target: https://community.openastronomy.org/ +.. |Zenodo - Latest DOI| image:: https://zenodo.org/badge/2165383.svg + :target: https://zenodo.org/badge/latestdoi/2165383 +.. |Continuous Integration Status| image:: https://github.com/sunpy/sunpy/actions/workflows/ci.yml/badge.svg?branch=main + :target: https://github.com/sunpy/sunpy/actions/workflows/ci.yml +.. |Google Groups Mailing List| image:: https://upload.wikimedia.org/wikipedia/commons/2/27/Google_Groups_logo.gif + :height: 20px + :target: https://groups.google.com/g/sunpy +.. |sunpy stable documentation| image:: https://readthedocs.org/projects/sunpy/badge/?version=stable + :target: https://docs.sunpy.org/ +.. |CodeCov Code Coverage| image:: https://codecov.io/gh/sunpy/sunpy/branch/main/graph/badge.svg + :target: https://codecov.io/gh/sunpy/sunpy +.. |Powered by NumFOCUS| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A + :target: https://numfocus.org +.. |sunpy citation| image:: https://img.shields.io/badge/cite-sunpy-orange + :target: https://docs.sunpy.org/en/stable/citation.html +.. |pyOpenSci| image:: https://tinyurl.com/y22nb8up + :target: https://github.com/pyOpenSci/software-submission/issues/147 + +``sunpy`` is a Python software package that provides fundamental tools for accessing, loading and interacting with solar physics data in Python. +It includes an interface for searching and downloading data from multiple data providers, data containers for image and time series data, commonly used solar coordinate frames and associated transformations, as well as other functionality needed for solar data analysis. + +Installation +============ + +We recommended following the `installation guide `__ in the ``sunpy`` documentation. +This will walk you through installing ``sunpy`` and all of its dependencies. + +Usage +===== + +If you are new to ``sunpy``, the best place to start is the `tutorial `__. +the `example gallery `__ also includes a collection of shorter and more specific examples of using ``sunpy``. + +Changes +======= + +See our `changelog `__. for the latest changes in ``sunpy``. + +Getting Help +============ + +For more information or to ask questions about ``sunpy`` or any other SunPy Project package, please check out: + +- `sunpy documentation `__ +- `SunPy Affiliated Packages `__ +- `SunPy Chat`_ +- `SunPy mailing list `__ +- `SunPy Community forum `__ + +Acknowledging or Citing ``sunpy`` +================================= + +If you use ``sunpy`` in your scientific work, we would appreciate your `citing it in your publications `__. +The continued growth and development of ``sunpy`` is dependent on the community being aware of ``sunpy``. + +Contributing +============ + +The SunPy Project is a community-driven open-source project that welcomes any and all contributions. +Whether you are a developer, student, or user, you can help by contributing code, documentation, or community support. + +If you would like to get involved, the `Newcomers Guide`_ guide explains the many different ways to contribute to the SunPy Project and also shows how to get set up with a development workflow. + +Help is always welcome, so come and say hello by joining the `SunPy Chat`_ and look over the `Good First Issues list`_ for the ideal places to start. + +.. _Newcomers Guide: https://docs.sunpy.org/en/latest/dev_guide/contents/newcomers.html +.. _Good First Issues list: https://github.com/sunpy/sunpy/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Good+First+Issue%22 + +Usage of Generative AI +====================== + +We expect authentic engagement in our community. +Be wary of posting output from Large Language Models or similar generative AI as comments on GitHub or any other platform, as such comments tend to be formulaic and low quality content. +If you use generative AI tools as an aid in developing code or documentation changes, ensure that you fully understand the proposed changes and can explain why they are the correct approach and an improvement to the current state. + +Code of Conduct +=============== + +When you are interacting with the SunPy Community you are asked to follow our `Code of Conduct `__. + +.. _SunPy Chat: https://app.element.io/#/room/#sunpy:openastronomy.org \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-unboundedsystems 2.md b/src/somef_core/test/test_data/README-unboundedsystems 2.md new file mode 100644 index 0000000..7183625 --- /dev/null +++ b/src/somef_core/test/test_data/README-unboundedsystems 2.md @@ -0,0 +1,86 @@ +[![Adapt logo](https://adaptjs.org/img/logo_lockup.svg)](https://adaptjs.org) + +[![npm](https://img.shields.io/npm/v/@adpt/cli?color=blue)](https://www.npmjs.com/package/@adpt/cli) +[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt) +[![License](https://img.shields.io/github/license/unboundedsystems/adapt)](https://opensource.org/licenses/Apache-2.0) + +# Adapt - ReactJS for your infrastructure. + +AdaptJS is a system to easily, reliably, and repeatably deploy your full-stack applications. Adapt specifications look like [React](https://reactjs.org) apps, but instead of rendering browser DOM elements like ``, or `
`, Adapt specifications use elements like AWS ``, Kubernetes ``, or `` database. + +If you're already familiar with React, you'll feel right at home with Adapt. +But if not, don't worry, knowledge of React isn't required to start using Adapt. + +## Getting Started + +For a new project, it's easy to get started with Adapt by using a starter template. +The [Getting Started Guide](https://adaptjs.org/docs/getting_started) will walk through installing Adapt and deploying your first starter app. + +## Creating and deploying an app + +This example creates a new full-stack app from a starter template. +It has a [React](https://reactjs.org) UI, an [Nginx](https://nginx.org) web server, a [Node.js](https://nodejs.org) API server, and a [Postgres](https://postgresql.org) database, then deploys it to [Kubernetes](https://kubernetes.io/): + +```bash +# Install adapt +npm install -g @adpt/cli + +# Create a new app from a starter template +adapt new hello-react-node-postgres ./myapp +cd myapp/deploy + +# Deploy full stack locally using Docker +adapt run laptop + +# Or just as easily deploy everything to Kubernetes +adapt run k8s-test +``` + +An Adapt description for a complete front end and back end app stack looks like this: + +```jsx +import Adapt from "@adpt/core"; +import { NodeService, ReactApp } from "@adpt/cloud/nodejs"; +import { Postgres } from "@adpt/cloud/postgres"; + +function MyApp() { + const pg = Adapt.handle(); + + return ( + + + + + + ); +} +``` + +## Adapt in action + +This demo shows using Adapt to create and deploy a simple app called MovieDB that has a [React](https://reactjs.org) UI, an [Nginx](https://nginx.org) web server, an Nginx URL router, a [Node.js](https://nodejs.org) API server, and a [Postgres](https://postgresql.org) database, then deploys it to [Kubernetes](https://kubernetes.io/): + +![Adapt in action](https://adaptjs.org/docs/assets/getting_started/adapt-demo-scaled.gif) + +## More info + +* [Adaptjs.org](https://adaptjs.org) + + Learn more about Adapt. + +* [Getting Started Guide](https://adaptjs.org/docs/getting_started) + + This guide will walk you through setting up Adapt and then deploying an example MovieDB app. + +* [Adapt Documentation](https://adaptjs.org/docs) + + Adapt tutorials, API References, and more. + +## Getting Help + +[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt) + +We'd love to hear about your experience with Adapt! +Join us on our [Gitter channel](https://gitter.im/UnboundedSystems/Adapt) to ask questions or to give us your feedback and suggestions. + +If you've found a bug, you can also [file an issue](https://gitlab.com/unboundedsystems/adapt/issues). diff --git a/src/somef_core/test/test_data/README-unboundedsystems.md b/src/somef_core/test/test_data/README-unboundedsystems.md new file mode 100644 index 0000000..7183625 --- /dev/null +++ b/src/somef_core/test/test_data/README-unboundedsystems.md @@ -0,0 +1,86 @@ +[![Adapt logo](https://adaptjs.org/img/logo_lockup.svg)](https://adaptjs.org) + +[![npm](https://img.shields.io/npm/v/@adpt/cli?color=blue)](https://www.npmjs.com/package/@adpt/cli) +[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt) +[![License](https://img.shields.io/github/license/unboundedsystems/adapt)](https://opensource.org/licenses/Apache-2.0) + +# Adapt - ReactJS for your infrastructure. + +AdaptJS is a system to easily, reliably, and repeatably deploy your full-stack applications. Adapt specifications look like [React](https://reactjs.org) apps, but instead of rendering browser DOM elements like ``, or `
`, Adapt specifications use elements like AWS ``, Kubernetes ``, or `` database. + +If you're already familiar with React, you'll feel right at home with Adapt. +But if not, don't worry, knowledge of React isn't required to start using Adapt. + +## Getting Started + +For a new project, it's easy to get started with Adapt by using a starter template. +The [Getting Started Guide](https://adaptjs.org/docs/getting_started) will walk through installing Adapt and deploying your first starter app. + +## Creating and deploying an app + +This example creates a new full-stack app from a starter template. +It has a [React](https://reactjs.org) UI, an [Nginx](https://nginx.org) web server, a [Node.js](https://nodejs.org) API server, and a [Postgres](https://postgresql.org) database, then deploys it to [Kubernetes](https://kubernetes.io/): + +```bash +# Install adapt +npm install -g @adpt/cli + +# Create a new app from a starter template +adapt new hello-react-node-postgres ./myapp +cd myapp/deploy + +# Deploy full stack locally using Docker +adapt run laptop + +# Or just as easily deploy everything to Kubernetes +adapt run k8s-test +``` + +An Adapt description for a complete front end and back end app stack looks like this: + +```jsx +import Adapt from "@adpt/core"; +import { NodeService, ReactApp } from "@adpt/cloud/nodejs"; +import { Postgres } from "@adpt/cloud/postgres"; + +function MyApp() { + const pg = Adapt.handle(); + + return ( + + + + + + ); +} +``` + +## Adapt in action + +This demo shows using Adapt to create and deploy a simple app called MovieDB that has a [React](https://reactjs.org) UI, an [Nginx](https://nginx.org) web server, an Nginx URL router, a [Node.js](https://nodejs.org) API server, and a [Postgres](https://postgresql.org) database, then deploys it to [Kubernetes](https://kubernetes.io/): + +![Adapt in action](https://adaptjs.org/docs/assets/getting_started/adapt-demo-scaled.gif) + +## More info + +* [Adaptjs.org](https://adaptjs.org) + + Learn more about Adapt. + +* [Getting Started Guide](https://adaptjs.org/docs/getting_started) + + This guide will walk you through setting up Adapt and then deploying an example MovieDB app. + +* [Adapt Documentation](https://adaptjs.org/docs) + + Adapt tutorials, API References, and more. + +## Getting Help + +[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt) + +We'd love to hear about your experience with Adapt! +Join us on our [Gitter channel](https://gitter.im/UnboundedSystems/Adapt) to ask questions or to give us your feedback and suggestions. + +If you've found a bug, you can also [file an issue](https://gitlab.com/unboundedsystems/adapt/issues). diff --git a/src/somef_core/test/test_data/README-uncbiag 2.md b/src/somef_core/test/test_data/README-uncbiag 2.md new file mode 100644 index 0000000..49a45ef --- /dev/null +++ b/src/somef_core/test/test_data/README-uncbiag 2.md @@ -0,0 +1,91 @@ +![Demo figure](notebooks/paper_figures/Intro_NewLabels-2.png) + + +# ICON: Learning Regular Maps through Inverse Consistency + +[](https://github.com/uncbiag/ICON/actions) +[](https://pypi.org/project/icon-registration) +[](https://icon.readthedocs.io/en/master/) + + +This is the official repository for + +**ICON: Learning Regular Maps through Inverse Consistency.** +Hastings Greer, Roland Kwitt, Francois-Xavier Vialard, Marc Niethammer. +_ICCV 2021_ https://arxiv.org/abs/2105.04459 + +**GradICON: Approximate Diffeomorphisms via Gradient Inverse Consistency.** +Lin Tian, Hastings Greer, Francois-Xavier Vialard, Roland Kwitt, Raúl San José Estépar, Marc Niethammer. +_CVPR 2023_ https://arxiv.org/abs/2206.05897 + +**Inverse Consistency by Construction for Multistep Deep Registration.** +Hastings Greer, Lin Tian, Francois-Xavier Vialard, Roland Kwitt, Sylvain Bouix, Raul San Jose Estepar, Richard Rushmore and Marc Niethammer. +_MICCAI 2023_ https://arxiv.org/abs/2305.00087 + +## Cite this work +``` +@InProceedings{Greer_2021_ICCV, + author = {Greer, Hastings and Kwitt, Roland and Vialard, Francois-Xavier and Niethammer, Marc}, + title = {ICON: Learning Regular Maps Through Inverse Consistency}, + booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV)}, + month = {October}, + year = {2021}, + pages = {3396-3405} +} +``` + +``` +@article{Tian_2022_arXiv, + title={GradICON: Approximate Diffeomorphisms via Gradient Inverse Consistency}, + author={Tian, Lin and Greer, Hastings and Vialard, Fran{\c{c}}ois-Xavier and Kwitt, Roland and Est{\'e}par, Ra{\'u}l San Jos{\'e} and Niethammer, Marc}, + journal={arXiv preprint arXiv:2206.05897}, + year={2022} +} +``` +``` +@misc{greer2023inverseconsistencyconstructionmultistep, + title={Inverse Consistency by Construction for Multistep Deep Registration}, + author={Hastings Greer and Lin Tian and Francois-Xavier Vialard and Roland Kwitt and Sylvain Bouix and Raul San Jose Estepar and Richard Rushmore and Marc Niethammer}, + year={2023}, + eprint={2305.00087}, + archivePrefix={arXiv}, + primaryClass={cs.CV}, + url={https://arxiv.org/abs/2305.00087}, +} +``` + + +## uniGradICON and multiGradICON + +If you are interested in general purpose deep learning registration approaches check out [uniGradICON and multiGradICON](https://github.com/uncbiag/uniGradICON). These networks were trained using the GradICON technology but over many different datasets allowing them to generalize to different unimodal and multimodal registration tasks. + +## Video Presentation + +[](https://youtu.be/7kZsJ3zWDCA) + + +## Running our code + +We are available on PyPI! +```bash +pip install icon-registration +``` + + +To run our pretrained model in the cloud on sample images from OAI knees, visit [our knee google colab notebook](https://colab.research.google.com/drive/1svftgw-vYWnLp9lSf3UkrG547atjbIrg?usp=sharing) + +To run our pretrained model for lung CT scans on an example from COPDgene, visit [our lung google colab notebook](https://colab.research.google.com/github/uncbiag/ICON/blob/master/notebooks/ICON_lung_demo.ipynb) + +---------------- + +To train from scratch on the synthetic triangles and circles dataset: + +```bash +git clone https://github.com/uncbiag/ICON +cd ICON + +pip install -e . + +python training_scripts/2d_triangles_example.py +``` + diff --git a/src/somef_core/test/test_data/README-uncbiag.md b/src/somef_core/test/test_data/README-uncbiag.md new file mode 100644 index 0000000..49a45ef --- /dev/null +++ b/src/somef_core/test/test_data/README-uncbiag.md @@ -0,0 +1,91 @@ +![Demo figure](notebooks/paper_figures/Intro_NewLabels-2.png) + + +# ICON: Learning Regular Maps through Inverse Consistency + +[](https://github.com/uncbiag/ICON/actions) +[](https://pypi.org/project/icon-registration) +[](https://icon.readthedocs.io/en/master/) + + +This is the official repository for + +**ICON: Learning Regular Maps through Inverse Consistency.** +Hastings Greer, Roland Kwitt, Francois-Xavier Vialard, Marc Niethammer. +_ICCV 2021_ https://arxiv.org/abs/2105.04459 + +**GradICON: Approximate Diffeomorphisms via Gradient Inverse Consistency.** +Lin Tian, Hastings Greer, Francois-Xavier Vialard, Roland Kwitt, Raúl San José Estépar, Marc Niethammer. +_CVPR 2023_ https://arxiv.org/abs/2206.05897 + +**Inverse Consistency by Construction for Multistep Deep Registration.** +Hastings Greer, Lin Tian, Francois-Xavier Vialard, Roland Kwitt, Sylvain Bouix, Raul San Jose Estepar, Richard Rushmore and Marc Niethammer. +_MICCAI 2023_ https://arxiv.org/abs/2305.00087 + +## Cite this work +``` +@InProceedings{Greer_2021_ICCV, + author = {Greer, Hastings and Kwitt, Roland and Vialard, Francois-Xavier and Niethammer, Marc}, + title = {ICON: Learning Regular Maps Through Inverse Consistency}, + booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV)}, + month = {October}, + year = {2021}, + pages = {3396-3405} +} +``` + +``` +@article{Tian_2022_arXiv, + title={GradICON: Approximate Diffeomorphisms via Gradient Inverse Consistency}, + author={Tian, Lin and Greer, Hastings and Vialard, Fran{\c{c}}ois-Xavier and Kwitt, Roland and Est{\'e}par, Ra{\'u}l San Jos{\'e} and Niethammer, Marc}, + journal={arXiv preprint arXiv:2206.05897}, + year={2022} +} +``` +``` +@misc{greer2023inverseconsistencyconstructionmultistep, + title={Inverse Consistency by Construction for Multistep Deep Registration}, + author={Hastings Greer and Lin Tian and Francois-Xavier Vialard and Roland Kwitt and Sylvain Bouix and Raul San Jose Estepar and Richard Rushmore and Marc Niethammer}, + year={2023}, + eprint={2305.00087}, + archivePrefix={arXiv}, + primaryClass={cs.CV}, + url={https://arxiv.org/abs/2305.00087}, +} +``` + + +## uniGradICON and multiGradICON + +If you are interested in general purpose deep learning registration approaches check out [uniGradICON and multiGradICON](https://github.com/uncbiag/uniGradICON). These networks were trained using the GradICON technology but over many different datasets allowing them to generalize to different unimodal and multimodal registration tasks. + +## Video Presentation + +[](https://youtu.be/7kZsJ3zWDCA) + + +## Running our code + +We are available on PyPI! +```bash +pip install icon-registration +``` + + +To run our pretrained model in the cloud on sample images from OAI knees, visit [our knee google colab notebook](https://colab.research.google.com/drive/1svftgw-vYWnLp9lSf3UkrG547atjbIrg?usp=sharing) + +To run our pretrained model for lung CT scans on an example from COPDgene, visit [our lung google colab notebook](https://colab.research.google.com/github/uncbiag/ICON/blob/master/notebooks/ICON_lung_demo.ipynb) + +---------------- + +To train from scratch on the synthetic triangles and circles dataset: + +```bash +git clone https://github.com/uncbiag/ICON +cd ICON + +pip install -e . + +python training_scripts/2d_triangles_example.py +``` + diff --git a/src/somef_core/test/test_data/README-widoco-duplicate-dois 2.md b/src/somef_core/test/test_data/README-widoco-duplicate-dois 2.md new file mode 100644 index 0000000..85fb4f0 --- /dev/null +++ b/src/somef_core/test/test_data/README-widoco-duplicate-dois 2.md @@ -0,0 +1,198 @@ +# WIzard for DOCumenting Ontologies (WIDOCO) +[![DOI](https://zenodo.org/badge/11427075.svg)](https://zenodo.org/badge/latestdoi/11427075) [![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) + +![Logo](src/main/resources/logo/logo2.png) + +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. + +**Author**: Daniel Garijo Verdejo (@dgarijo) + +**Contributors**: María Poveda, Idafen Santana, Almudena Ruiz, Miguel Angel García, Oscar Corcho, Daniel Vila, Sergio Barrio, Martin Scharm, Maxime Lefrancois, Alfredo Serafini, @kartgk, Pat Mc Bennett, Christophe Camel, Jacobus Geluk, Martin Scharm, @rpietzsch, Jonathan Leitschuh, Jodi Schneider, Giacomo Lanza, Alejandra Gonzalez-Beltran, Mario Scrocca, Miguel Angel García and Flores Bakker. + +**Citing WIDOCO**: If you used WIDOCO in your work, please cite the ISWC 2017 paper: https://iswc2017.semanticweb.org/paper-138 + +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} + +@inproceedings{garijo2017widoco_duplicate, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {https://dx.doi.org/10.1007/978-3-319-68204-4_9}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +If you want to cite the latest version of the software, you can do so by using: https://zenodo.org/badge/latestdoi/11427075. + +## Downloading the executable + +To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest). + +## Importing WIDOCO as a dependency +Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project. + +```xml + + + com.github.dgarijo + Widoco + v1.4.15 + + + +[ ... ] + + + + jitpack.io + https://jitpack.io + + +``` + +## Description +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology. + +Features of WIDOCO: +* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html)) +* Automatic annotation in JSON-LD snippets of the html produced. +* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant). +* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO. +* Guidelines on the main sections that your document should have and how to complete them. +* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)). +* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)). +* Separation of the sections of your html page so you can write them independently and replace only those needed. +* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/) +* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/)) +* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology. + +## Examples +Examples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/) + +## GUI Tutorial +A tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) + +## How to use WIDOCO + +### JAR execution + +Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file. + +You may also execute WIDOCO through the command line. Usage: +```bash +java -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS] +``` + +### Docker execution + +First build the image using the `Dockerfile` in project folder: + +```bash +docker build -t dgarijo/widoco . +``` + +You can now execute WIDOCO through the command line. Usage: + +```bash +docker run -ti --rm dgarijo/widoco [OPTIONS] +``` + +If you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container +with host directories. For instance: + +```bash +docker run -ti --rm \ + -v `pwd`/test:/usr/local/widoco/in \ + -v `pwd`/target/generated-doc:/usr/local/widoco/out \ + dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll +``` + +### Options + +`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI + +`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile + +`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation' + +`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata + +`-getOntologyMetadata`: Extract ontology metadata from the given ontology + +`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/) + +`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution) + +`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists. + +`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology + +`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila). + +`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by "-"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es + +`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not. + +`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server. + +`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation. + +`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled. + +`-ignoreIndividuals`: Individuals will not be included in the documentation. + +`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included) + +`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234 + +`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed. + +`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented. + +`-rewriteBase PATH`: Change the default rewrite base path. The default value is "/". This flag can only be used with the htaccess option. + +`-excludeIntroduction`: Skip the introduction section in the documentation. + +`-uniteSections`: Write all HTML sections into a single HTML document. + +`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections). + +`--help`: Shows a help message and exits. + + +## How can I make WIDOCO automatically recognize my vocabulary annotations? +There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. + +* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend. +* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ";" is used for lists (for instance first author; second author; third author). + +## Browser issues (Why can't I see the generated documentation / visualization?) +WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options: + +* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the "load sections" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally. +* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers). + +If you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately. + +## Current improvements +For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository. + +## Requirements +You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work +Otherwise, you will probably experience an "Unsupported major.minor version 52.0" exception when executing the JAR file. + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. diff --git a/src/somef_core/test/test_data/README-widoco-duplicate-dois.md b/src/somef_core/test/test_data/README-widoco-duplicate-dois.md new file mode 100644 index 0000000..85fb4f0 --- /dev/null +++ b/src/somef_core/test/test_data/README-widoco-duplicate-dois.md @@ -0,0 +1,198 @@ +# WIzard for DOCumenting Ontologies (WIDOCO) +[![DOI](https://zenodo.org/badge/11427075.svg)](https://zenodo.org/badge/latestdoi/11427075) [![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) + +![Logo](src/main/resources/logo/logo2.png) + +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. + +**Author**: Daniel Garijo Verdejo (@dgarijo) + +**Contributors**: María Poveda, Idafen Santana, Almudena Ruiz, Miguel Angel García, Oscar Corcho, Daniel Vila, Sergio Barrio, Martin Scharm, Maxime Lefrancois, Alfredo Serafini, @kartgk, Pat Mc Bennett, Christophe Camel, Jacobus Geluk, Martin Scharm, @rpietzsch, Jonathan Leitschuh, Jodi Schneider, Giacomo Lanza, Alejandra Gonzalez-Beltran, Mario Scrocca, Miguel Angel García and Flores Bakker. + +**Citing WIDOCO**: If you used WIDOCO in your work, please cite the ISWC 2017 paper: https://iswc2017.semanticweb.org/paper-138 + +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} + +@inproceedings{garijo2017widoco_duplicate, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {https://dx.doi.org/10.1007/978-3-319-68204-4_9}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +If you want to cite the latest version of the software, you can do so by using: https://zenodo.org/badge/latestdoi/11427075. + +## Downloading the executable + +To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest). + +## Importing WIDOCO as a dependency +Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project. + +```xml + + + com.github.dgarijo + Widoco + v1.4.15 + + + +[ ... ] + + + + jitpack.io + https://jitpack.io + + +``` + +## Description +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology. + +Features of WIDOCO: +* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html)) +* Automatic annotation in JSON-LD snippets of the html produced. +* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant). +* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO. +* Guidelines on the main sections that your document should have and how to complete them. +* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)). +* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)). +* Separation of the sections of your html page so you can write them independently and replace only those needed. +* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/) +* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/)) +* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology. + +## Examples +Examples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/) + +## GUI Tutorial +A tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) + +## How to use WIDOCO + +### JAR execution + +Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file. + +You may also execute WIDOCO through the command line. Usage: +```bash +java -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS] +``` + +### Docker execution + +First build the image using the `Dockerfile` in project folder: + +```bash +docker build -t dgarijo/widoco . +``` + +You can now execute WIDOCO through the command line. Usage: + +```bash +docker run -ti --rm dgarijo/widoco [OPTIONS] +``` + +If you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container +with host directories. For instance: + +```bash +docker run -ti --rm \ + -v `pwd`/test:/usr/local/widoco/in \ + -v `pwd`/target/generated-doc:/usr/local/widoco/out \ + dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll +``` + +### Options + +`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI + +`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile + +`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation' + +`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata + +`-getOntologyMetadata`: Extract ontology metadata from the given ontology + +`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/) + +`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution) + +`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists. + +`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology + +`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila). + +`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by "-"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es + +`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not. + +`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server. + +`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation. + +`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled. + +`-ignoreIndividuals`: Individuals will not be included in the documentation. + +`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included) + +`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234 + +`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed. + +`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented. + +`-rewriteBase PATH`: Change the default rewrite base path. The default value is "/". This flag can only be used with the htaccess option. + +`-excludeIntroduction`: Skip the introduction section in the documentation. + +`-uniteSections`: Write all HTML sections into a single HTML document. + +`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections). + +`--help`: Shows a help message and exits. + + +## How can I make WIDOCO automatically recognize my vocabulary annotations? +There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. + +* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend. +* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ";" is used for lists (for instance first author; second author; third author). + +## Browser issues (Why can't I see the generated documentation / visualization?) +WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options: + +* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the "load sections" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally. +* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers). + +If you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately. + +## Current improvements +For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository. + +## Requirements +You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work +Otherwise, you will probably experience an "Unsupported major.minor version 52.0" exception when executing the JAR file. + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. diff --git a/src/somef_core/test/test_data/README-widoco-swh 2.md b/src/somef_core/test/test_data/README-widoco-swh 2.md new file mode 100644 index 0000000..0f72c58 --- /dev/null +++ b/src/somef_core/test/test_data/README-widoco-swh 2.md @@ -0,0 +1,233 @@ +# WIzard for DOCumenting Ontologies (WIDOCO) +[![DOI](https://zenodo.org/badge/11427075.svg)](https://doi.org/10.5281/zenodo.11093793) [![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![SWH](https://archive.softwareheritage.org/badge/origin/https://github.com/dgarijo/Widoco/)](https://archive.softwareheritage.org/browse/origin/?origin_url=https://github.com/dgarijo/Widoco) [![SWH](https://archive.softwareheritage.org/badge/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7/)](https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7;origin=https://github.com/dgarijo/Widoco;visit=swh:1:snp:4d8570d390a18fee1d37f262ad79b36c021c611a;anchor=swh:1:rev:fec66b89a4f4acb015a44c7f8cb671d49bec626a) + +![Logo](src/main/resources/logo/logo2.png) + +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. + +**Author**: Daniel Garijo Verdejo (@dgarijo) + +**Contributors**: María Poveda, Idafen Santana, Almudena Ruiz, Miguel Angel García, Oscar Corcho, Daniel Vila, Sergio Barrio, Martin Scharm, Maxime Lefrancois, Alfredo Serafini, @kartgk, Pat Mc Bennett, Christophe Camel, Jacobus Geluk, Martin Scharm, @rpietzsch, Jonathan Leitschuh, Jodi Schneider, Giacomo Lanza, Alejandra Gonzalez-Beltran, Mario Scrocca, Miguel Angel García, Flores Bakker, @JohnnyMoonlight, René Fritze, @telecsur, Jan Vlug, Han Kruiger, Johannes Theissen-Lipp, Roberto Polli, Victor Chavez, Sirko Schindler and Michaël Dierick. + +**Citing WIDOCO**: If you used WIDOCO in your work, please cite the ISWC 2017 paper: https://iswc2017.semanticweb.org/paper-138 + +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +If you want to cite the latest version of the software, you can do so by using: https://zenodo.org/badge/latestdoi/11427075. + +## Downloading the executable + +To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest). + +## Importing WIDOCO as a dependency +Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project. + +```xml + + + com.github.dgarijo + Widoco + v1.4.24 + + + +[ ... ] + + + + jitpack.io + https://jitpack.io + + +``` + +## Description +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology. + +Features of WIDOCO: +* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html)) +* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information. +* Automatic annotation in JSON-LD snippets of the html produced. +* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant). +* Guidelines on the main sections that your document should have and how to complete them. +* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)). +* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)). +* Separation of the sections of your html page so you can write them independently and replace only those needed. +* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/) +* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/)) +* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology. + +## Examples +Examples of the features of WIDOCO can be seen on [the gallery](https://dgarijo.github.io/Widoco/doc/gallery/) + +## GUI Tutorial +A tutorial explaining the main features of the GUI can be found [here](https://dgarijo.github.io/Widoco/doc/tutorial/) + +## Metadata usage +To see how WIDOCO recognizes metadata annotations in your ontology to create the documentation files, see [the WIDOCO metadata documentation](doc/metadataGuide/guide.md). To learn which metadata properties we recommend adding to your ontology for producing a nice-looking documentation, have a look at our [best practices guide](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html). + +For example, in order to show your logo in your documentation you just need to use `foaf:logo` as an annotation, as follows: +``` +@prefix owl: . +@prefix foaf: . + a owl:Ontology ; + foaf:logo . +``` + +and it will show right next to the title. The [WIDOCO metadata documentation](doc/metadataGuide/guide.md) shows all supported metadata fields. + +## How to use WIDOCO + +### Building the JAR executable +We provide JAR files for each release (see the [releases](https://github.com/dgarijo/Widoco/releases) page). However, if you want to build WIDOCO from scratch, just cd into the project folder and run: + +```bash +mvn install +``` +The JAR will be generated in a "JAR" folder. The name will follow the pattern: `widoco-{VERSION_ID}-jar-with-dependencies.jar`, where {VERSION_ID} is the version number of the tool. + +### JAR execution + +Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file. + +You may also execute WIDOCO through the command line. Usage: +```bash +java -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS] +``` + +### Docker execution +If you don't want to use the JAR directly, you may run the project using a [Docker container](https://www.docker.com/). First you will need to download or build the image, and then run it. + +#### Reusing a pre-existing image +We build containers in the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco) for all latest releases. In order to import one, just run the following command, stating the version of Widoco you prefer (e.g., for v1.4.23): + +``` +docker pull ghcr.io/dgarijo/widoco:v1.4.23 +``` + +To browse all available images, see the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco). + +#### Building the image yourself + +Build the image using the `Dockerfile` in project folder: + +```bash +docker build -t dgarijo/widoco . +``` + +#### Running WIDOCO's image + +You can now execute WIDOCO through the command line. Usage: + +```bash +docker run -ti --rm dgarijo/widoco [OPTIONS] +``` + +**Note:** If you downloaded the image from the GitHub registry, you will have to change `dgarijo/widoco` with the name of the image you downloaded. For example `ghcr.io/dgarijo/widoco:v1.4.23`. + +If you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container +with host directories. For instance: + +```bash +docker run -ti --rm \ + -v `pwd`/test:/usr/local/widoco/in:Z \ + -v `pwd`/target/generated-doc:/usr/local/widoco/out:Z \ + dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll +``` + +### Execution options + +`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234 + +`-confFile PATH`: Load your own configuration file for the ontology metadata. Use this option if you want to load your own HTML sections as well. Incompatible with -getOntologyMetadata. See [the configuration documentation](doc/configuration/configuration_doc.md) for more information about the accepted fields. + +`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists. + +`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented. + +`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed. + +`-excludeIntroduction`: Skip the introduction section in the documentation. + +`-excludeProvenance`: Do not add the link "Provenance of this page" in the metadata header section + +`-getOntologyMetadata`: Extract ontology metadata from the given ontology + +`--help`: Shows a help message and exits. + +`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server. + + +`-ignoreIndividuals`: Individuals will not be included in the documentation. + +`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included) + +`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not. + +`-import`: imports a local ontology (e.g., if you don't want to load an online ontology, you may load its local version) + +`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by "-"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es + +`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled. + +`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections). + +`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI + +`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation' + +`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile + +`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/) + +`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution) + +`-rewriteBase PATH`: Change the default rewrite base path. The default value is "/". This flag can only be used with the htaccess option. + +`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology + +`-uniteSections`: Write all HTML sections into a single HTML document. + +`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila). + +`--version`: Shows the current version of WIDOCO. + +`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation. + + +## How can I make WIDOCO automatically recognize my vocabulary annotations? +There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. + +* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend. +* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ";" is used for lists (for instance first author; second author; third author). + +For more information, see the [Widoco metadata guide](doc/metadataGuide/guide.md) + +## Browser issues (Why can't I see the generated documentation / visualization?) +WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options: + +* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the "load sections" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally. +* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers). + +If you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately. + +## Current improvements +For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository. + +## Requirements +You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work +Otherwise, you will probably experience an "Unsupported major.minor version 52.0" exception when executing the JAR file. + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \ No newline at end of file diff --git a/src/somef_core/test/test_data/README-widoco-swh.md b/src/somef_core/test/test_data/README-widoco-swh.md new file mode 100644 index 0000000..0f72c58 --- /dev/null +++ b/src/somef_core/test/test_data/README-widoco-swh.md @@ -0,0 +1,233 @@ +# WIzard for DOCumenting Ontologies (WIDOCO) +[![DOI](https://zenodo.org/badge/11427075.svg)](https://doi.org/10.5281/zenodo.11093793) [![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![SWH](https://archive.softwareheritage.org/badge/origin/https://github.com/dgarijo/Widoco/)](https://archive.softwareheritage.org/browse/origin/?origin_url=https://github.com/dgarijo/Widoco) [![SWH](https://archive.softwareheritage.org/badge/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7/)](https://archive.softwareheritage.org/swh:1:dir:40d462bbecefc3a9c3e810567d1f0d7606e0fae7;origin=https://github.com/dgarijo/Widoco;visit=swh:1:snp:4d8570d390a18fee1d37f262ad79b36c021c611a;anchor=swh:1:rev:fec66b89a4f4acb015a44c7f8cb671d49bec626a) + +![Logo](src/main/resources/logo/logo2.png) + +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. + +**Author**: Daniel Garijo Verdejo (@dgarijo) + +**Contributors**: María Poveda, Idafen Santana, Almudena Ruiz, Miguel Angel García, Oscar Corcho, Daniel Vila, Sergio Barrio, Martin Scharm, Maxime Lefrancois, Alfredo Serafini, @kartgk, Pat Mc Bennett, Christophe Camel, Jacobus Geluk, Martin Scharm, @rpietzsch, Jonathan Leitschuh, Jodi Schneider, Giacomo Lanza, Alejandra Gonzalez-Beltran, Mario Scrocca, Miguel Angel García, Flores Bakker, @JohnnyMoonlight, René Fritze, @telecsur, Jan Vlug, Han Kruiger, Johannes Theissen-Lipp, Roberto Polli, Victor Chavez, Sirko Schindler and Michaël Dierick. + +**Citing WIDOCO**: If you used WIDOCO in your work, please cite the ISWC 2017 paper: https://iswc2017.semanticweb.org/paper-138 + +```bib +@inproceedings{garijo2017widoco, + title={WIDOCO: a wizard for documenting ontologies}, + author={Garijo, Daniel}, + booktitle={International Semantic Web Conference}, + pages={94--102}, + year={2017}, + organization={Springer, Cham}, + doi = {10.1007/978-3-319-68204-4_9}, + funding = {USNSF ICER-1541029, NIH 1R01GM117097-01}, + url={http://dgarijo.com/papers/widoco-iswc2017.pdf} +} +``` +If you want to cite the latest version of the software, you can do so by using: https://zenodo.org/badge/latestdoi/11427075. + +## Downloading the executable + +To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest). + +## Importing WIDOCO as a dependency +Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project. + +```xml + + + com.github.dgarijo + Widoco + v1.4.24 + + + +[ ... ] + + + + jitpack.io + https://jitpack.io + + +``` + +## Description +WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology. + +Features of WIDOCO: +* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html)) +* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information. +* Automatic annotation in JSON-LD snippets of the html produced. +* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant). +* Guidelines on the main sections that your document should have and how to complete them. +* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)). +* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)). +* Separation of the sections of your html page so you can write them independently and replace only those needed. +* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/) +* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/)) +* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology. + +## Examples +Examples of the features of WIDOCO can be seen on [the gallery](https://dgarijo.github.io/Widoco/doc/gallery/) + +## GUI Tutorial +A tutorial explaining the main features of the GUI can be found [here](https://dgarijo.github.io/Widoco/doc/tutorial/) + +## Metadata usage +To see how WIDOCO recognizes metadata annotations in your ontology to create the documentation files, see [the WIDOCO metadata documentation](doc/metadataGuide/guide.md). To learn which metadata properties we recommend adding to your ontology for producing a nice-looking documentation, have a look at our [best practices guide](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html). + +For example, in order to show your logo in your documentation you just need to use `foaf:logo` as an annotation, as follows: +``` +@prefix owl: . +@prefix foaf: . + a owl:Ontology ; + foaf:logo . +``` + +and it will show right next to the title. The [WIDOCO metadata documentation](doc/metadataGuide/guide.md) shows all supported metadata fields. + +## How to use WIDOCO + +### Building the JAR executable +We provide JAR files for each release (see the [releases](https://github.com/dgarijo/Widoco/releases) page). However, if you want to build WIDOCO from scratch, just cd into the project folder and run: + +```bash +mvn install +``` +The JAR will be generated in a "JAR" folder. The name will follow the pattern: `widoco-{VERSION_ID}-jar-with-dependencies.jar`, where {VERSION_ID} is the version number of the tool. + +### JAR execution + +Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file. + +You may also execute WIDOCO through the command line. Usage: +```bash +java -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS] +``` + +### Docker execution +If you don't want to use the JAR directly, you may run the project using a [Docker container](https://www.docker.com/). First you will need to download or build the image, and then run it. + +#### Reusing a pre-existing image +We build containers in the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco) for all latest releases. In order to import one, just run the following command, stating the version of Widoco you prefer (e.g., for v1.4.23): + +``` +docker pull ghcr.io/dgarijo/widoco:v1.4.23 +``` + +To browse all available images, see the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco). + +#### Building the image yourself + +Build the image using the `Dockerfile` in project folder: + +```bash +docker build -t dgarijo/widoco . +``` + +#### Running WIDOCO's image + +You can now execute WIDOCO through the command line. Usage: + +```bash +docker run -ti --rm dgarijo/widoco [OPTIONS] +``` + +**Note:** If you downloaded the image from the GitHub registry, you will have to change `dgarijo/widoco` with the name of the image you downloaded. For example `ghcr.io/dgarijo/widoco:v1.4.23`. + +If you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container +with host directories. For instance: + +```bash +docker run -ti --rm \ + -v `pwd`/test:/usr/local/widoco/in:Z \ + -v `pwd`/target/generated-doc:/usr/local/widoco/out:Z \ + dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll +``` + +### Execution options + +`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234 + +`-confFile PATH`: Load your own configuration file for the ontology metadata. Use this option if you want to load your own HTML sections as well. Incompatible with -getOntologyMetadata. See [the configuration documentation](doc/configuration/configuration_doc.md) for more information about the accepted fields. + +`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists. + +`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented. + +`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed. + +`-excludeIntroduction`: Skip the introduction section in the documentation. + +`-excludeProvenance`: Do not add the link "Provenance of this page" in the metadata header section + +`-getOntologyMetadata`: Extract ontology metadata from the given ontology + +`--help`: Shows a help message and exits. + +`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server. + + +`-ignoreIndividuals`: Individuals will not be included in the documentation. + +`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included) + +`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not. + +`-import`: imports a local ontology (e.g., if you don't want to load an online ontology, you may load its local version) + +`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by "-"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es + +`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled. + +`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections). + +`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI + +`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation' + +`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile + +`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/) + +`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution) + +`-rewriteBase PATH`: Change the default rewrite base path. The default value is "/". This flag can only be used with the htaccess option. + +`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology + +`-uniteSections`: Write all HTML sections into a single HTML document. + +`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila). + +`--version`: Shows the current version of WIDOCO. + +`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation. + + +## How can I make WIDOCO automatically recognize my vocabulary annotations? +There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. + +* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend. +* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ";" is used for lists (for instance first author; second author; third author). + +For more information, see the [Widoco metadata guide](doc/metadataGuide/guide.md) + +## Browser issues (Why can't I see the generated documentation / visualization?) +WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options: + +* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the "load sections" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally. +* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers). + +If you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately. + +## Current improvements +For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository. + +## Requirements +You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work +Otherwise, you will probably experience an "Unsupported major.minor version 52.0" exception when executing the JAR file. + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \ No newline at end of file diff --git a/src/somef_core/test/test_data/api_responses/somef-demo.json b/src/somef_core/test/test_data/api_responses/somef-demo.json new file mode 100644 index 0000000..15434bb --- /dev/null +++ b/src/somef_core/test/test_data/api_responses/somef-demo.json @@ -0,0 +1,648 @@ +{ + "somef_provenance": { + "somef_version": "0.9.12", + "somef_schema_version": "1.0.0", + "date": "2025-12-10 11:21:43" + }, + "code_repository": [ + { + "result": { + "value": "https://github.com/juanjemdIos/somef-demo-repo", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "owner": [ + { + "result": { + "value": "juanjemdIos", + "type": "User" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "date_created": [ + { + "result": { + "value": "2025-04-23T13:26:06Z", + "type": "Date" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "date_updated": [ + { + "result": { + "value": "2025-05-05T06:57:47Z", + "type": "Date" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "license": [ + { + "result": { + "value": "https://api.github.com/licenses/agpl-3.0", + "type": "License", + "name": "GNU Affero General Public License v3.0", + "url": "https://api.github.com/licenses/agpl-3.0", + "spdx_id": "AGPL-3.0" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": " GNU AFFERO GENERAL PUBLIC LICENSE\n Version 3, 19 November 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. \n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n Preamble\n\n The GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\n The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works. By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\n When we speak of free software, we are referring to freedom, not\nprice. Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n Developers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\n A secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate. Many developers of free software are heartened and\nencouraged by the resulting cooperation. However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\n The GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community. It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server. Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\n An older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals. This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\n The precise terms and conditions for copying, distribution and\nmodification follow.\n\n TERMS AND CONDITIONS\n\n 0. Definitions.\n\n \"This License\" refers to version 3 of the GNU Affero General Public License.\n\n \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n \"The Program\" refers to any copyrightable work licensed under this\nLicense. Each licensee is addressed as \"you\". \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy. The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy. Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies. Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License. If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n 1. Source Code.\n\n The \"source code\" for a work means the preferred form of the work\nfor making modifications to it. \"Object code\" means any non-source\nform of a work.\n\n A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form. A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities. However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work. For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n The Corresponding Source for a work in source code form is that\nsame work.\n\n 2. Basic Permissions.\n\n All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met. This License explicitly affirms your unlimited\npermission to run the unmodified Program. The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work. This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force. You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright. Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n Conveying under any other circumstances is permitted solely under\nthe conditions stated below. Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n 4. Conveying Verbatim Copies.\n\n You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n 5. Conveying Modified Source Versions.\n\n You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n a) The work must carry prominent notices stating that you modified\n it, and giving a relevant date.\n\n b) The work must carry prominent notices stating that it is\n released under this License and any conditions added under section\n 7. This requirement modifies the requirement in section 4 to\n \"keep intact all notices\".\n\n c) You must license the entire work, as a whole, under this\n License to anyone who comes into possession of a copy. This\n License will therefore apply, along with any applicable section 7\n additional terms, to the whole of the work, and all its parts,\n regardless of how they are packaged. This License gives no\n permission to license the work in any other way, but it does not\n invalidate such permission if you have separately received it.\n\n d) If the work has interactive user interfaces, each must display\n Appropriate Legal Notices; however, if the Program has interactive\n interfaces that do not display Appropriate Legal Notices, your\n work need not make them do so.\n\n A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit. Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n 6. Conveying Non-Source Forms.\n\n You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n a) Convey the object code in, or embodied in, a physical product\n (including a physical distribution medium), accompanied by the\n Corresponding Source fixed on a durable physical medium\n customarily used for software interchange.\n\n b) Convey the object code in, or embodied in, a physical product\n (including a physical distribution medium), accompanied by a\n written offer, valid for at least three years and valid for as\n long as you offer spare parts or customer support for that product\n model, to give anyone who possesses the object code either (1) a\n copy of the Corresponding Source for all the software in the\n product that is covered by this License, on a durable physical\n medium customarily used for software interchange, for a price no\n more than your reasonable cost of physically performing this\n conveying of source, or (2) access to copy the\n Corresponding Source from a network server at no charge.\n\n c) Convey individual copies of the object code with a copy of the\n written offer to provide the Corresponding Source. This\n alternative is allowed only occasionally and noncommercially, and\n only if you received the object code with such an offer, in accord\n with subsection 6b.\n\n d) Convey the object code by offering access from a designated\n place (gratis or for a charge), and offer equivalent access to the\n Corresponding Source in the same way through the same place at no\n further charge. You need not require recipients to copy the\n Corresponding Source along with the object code. If the place to\n copy the object code is a network server, the Corresponding Source\n may be on a different server (operated by you or a third party)\n that supports equivalent copying facilities, provided you maintain\n clear directions next to the object code saying where to find the\n Corresponding Source. Regardless of what server hosts the\n Corresponding Source, you remain obligated to ensure that it is\n available for as long as needed to satisfy these requirements.\n\n e) Convey the object code using peer-to-peer transmission, provided\n you inform other peers where the object code and Corresponding\n Source of the work are being offered to the general public at no\n charge under subsection 6d.\n\n A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling. In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage. For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product. A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source. The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information. But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed. Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n 7. Additional Terms.\n\n \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law. If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit. (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.) You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n a) Disclaiming warranty or limiting liability differently from the\n terms of sections 15 and 16 of this License; or\n\n b) Requiring preservation of specified reasonable legal notices or\n author attributions in that material or in the Appropriate Legal\n Notices displayed by works containing it; or\n\n c) Prohibiting misrepresentation of the origin of that material, or\n requiring that modified versions of such material be marked in\n reasonable ways as different from the original version; or\n\n d) Limiting the use for publicity purposes of names of licensors or\n authors of the material; or\n\n e) Declining to grant rights under trademark law for use of some\n trade names, trademarks, or service marks; or\n\n f) Requiring indemnification of licensors and authors of that\n material by anyone who conveys the material (or modified versions of\n it) with contractual assumptions of liability to the recipient, for\n any liability that these contractual assumptions directly impose on\n those licensors and authors.\n\n All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10. If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term. If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n 8. Termination.\n\n You may not propagate or modify a covered work except as expressly\nprovided under this License. Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License. If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n 9. Acceptance Not Required for Having Copies.\n\n You are not required to accept this License in order to receive or\nrun a copy of the Program. Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance. However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work. These actions infringe copyright if you do\nnot accept this License. Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n 10. Automatic Licensing of Downstream Recipients.\n\n Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License. You are not responsible\nfor enforcing compliance by third parties with this License.\n\n An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations. If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License. For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n 11. Patents.\n\n A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based. The\nwork thus licensed is called the contributor's \"contributor version\".\n\n A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version. For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement). To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients. \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License. You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n 12. No Surrender of Others' Freedom.\n\n If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License. If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all. For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n 13. Remote Network Interaction; Use with the GNU General Public License.\n\n Notwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software. This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\n Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work. The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n 14. Revised Versions of this License.\n\n The Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time. Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n Each version is given a distinguishing version number. If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation. If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n If the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n Later license versions may give you additional or different\npermissions. However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n 15. Disclaimer of Warranty.\n\n THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n 16. Limitation of Liability.\n\n IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n 17. Interpretation of Sections 15 and 16.\n\n If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n END OF TERMS AND CONDITIONS\n\n How to Apply These Terms to Your New Programs\n\n If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n To do so, attach the following notices to the program. It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n \n Copyright (C) \n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU Affero General Public License as published\n by the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU Affero General Public License for more details.\n\n You should have received a copy of the GNU Affero General Public License\n along with this program. If not, see .\n\nAlso add information on how to contact you by electronic and paper mail.\n\n If your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source. For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code. There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\n You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n.\n", + "type": "File_dump", + "name": "GNU Affero General Public License v3.0", + "spdx_id": "AGPL-3.0" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/LICENSE" + } + ], + "description": [ + { + "result": { + "value": "This repo aims to provide values for each metadata field that SOMEF (v0.9.10) can extract", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Text_excerpt", + "value": "[Yulun Zhang](http://yulunzhang.com/), [Yapeng Tian](http://yapengtian.org/), [Yu Kong](http://www1.ece.neu.edu/~yukong/), [Bineng Zhong](https://scholar.google.de/citations?user=hvRBydsAAAAJ&hl=en), and [Yun Fu](http://www1.ece.neu.edu/~yunfu/), \"Residual Dense Network for Image Super-Resolution\", CVPR 2018 (spotlight), [[arXiv]](https://arxiv.org/abs/1802.08797) \n \n", + "original_header": "Related papers" + }, + "confidence": 0.8559632720021659, + "technique": "supervised_classification", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "name": [ + { + "result": { + "value": "somef-demo-repo", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "full_name": [ + { + "result": { + "value": "juanjemdIos/somef-demo-repo", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "issue_tracker": [ + { + "result": { + "value": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/issues", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "forks_url": [ + { + "result": { + "value": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/forks", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "keywords": [ + { + "result": { + "value": "documentation, metadata, ontology, somef", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "download_url": [ + { + "result": { + "value": "https://github.com/juanjemdIos/somef-demo-repo/releases", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "programming_languages": [ + { + "result": { + "value": "Jupyter Notebook", + "name": "Jupyter Notebook", + "type": "Programming_language", + "size": 32402 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Common Workflow Language", + "name": "Common Workflow Language", + "type": "Programming_language", + "size": 492 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Dockerfile", + "name": "Dockerfile", + "type": "Programming_language", + "size": 265 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Shell", + "name": "Shell", + "type": "Programming_language", + "size": 35 + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "releases": [ + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/releases/214448249", + "tag": "0.0.1", + "name": "First releases", + "author": { + "name": "juanjemdIos", + "type": "User" + }, + "description": "This release only serves to be extracted by SOMEF into `releases`", + "tarball_url": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/tarball/0.0.1", + "zipball_url": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/zipball/0.0.1", + "html_url": "https://github.com/juanjemdIos/somef-demo-repo/releases/tag/0.0.1", + "url": "https://api.github.com/repos/juanjemdIos/somef-demo-repo/releases/214448249", + "release_id": 214448249, + "date_created": "2025-04-23T14:26:19Z", + "date_published": "2025-04-24T08:51:25Z", + "assets": [] + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "code_of_conduct": [ + { + "result": { + "value": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\n.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior, harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n", + "type": "File_dump" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/CODE_OF_CONDUCT.md" + } + ], + "executable_example": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/executable_example.ipynb", + "type": "Url", + "format": "jupyter_notebook" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/executable_example.ipynb" + } + ], + "has_script_file": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/script_file.sh", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "authors": [ + { + "result": { + "name": "Google Inc.", + "type": "Agent", + "value": "Google Inc." + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/AUTHORS" + }, + { + "result": { + "name": "Daniel Garijo", + "type": "Agent", + "value": "Daniel Garijo", + "email": "daniel.garijo@upm.es", + "last_name": "Garijo", + "given_name": "Daniel" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/AUTHORS" + }, + { + "result": { + "name": "Juanje Mendoza", + "type": "Agent", + "value": "Juanje Mendoza", + "email": "juanjesus.mendoza@fi.upm.es", + "last_name": "Mendoza", + "given_name": "Juanje" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/AUTHORS" + }, + { + "result": { + "name": "Arm Ltd", + "type": "Agent", + "value": "Arm Ltd" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/AUTHORS" + } + ], + "has_build_file": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/Dockerfile", + "type": "Url", + "format": "dockerfile" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/Dockerfile" + } + ], + "citation": [ + { + "result": { + "value": "cff-version: 1.2.0\nmessage: If you use this software, please cite it using these metadata.\ntitle: SOMEF DEMO REPO\nabstract: Demo repository for new version (0.9.10) of SOMEF \nauthors:\n - family-names: Thomas\n given-names: Pronk\n orcid: https://orcid.org/0000-0001-9334-7190\nversion: 0.0.1\ndate-released: 2023-11-23\nlicense: AGPL-3.0\nurl: \"https://github.com/tpronk/somef-demo-repo\"", + "type": "File_dump", + "author": [ + { + "type": "Agent", + "name": "Pronk Thomas", + "family_name": "Thomas", + "given_name": "Pronk", + "url": "https://orcid.org/0000-0001-9334-7190" + } + ], + "title": "SOMEF DEMO REPO", + "url": "https://github.com/tpronk/somef-demo-repo", + "format": "cff", + "datePublished": "2023" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/CITATION.cff" + }, + { + "result": { + "value": "Please cite this repo as Pronk, T. (2023). *somef-demo-repo: This repo aims to provide values for each metadata field that SOMEF (v0.9.4) can extract* (Version 0.0.1) [Computer software]. https://github.com/tpronk/somef-demo-repo\n", + "type": "Text_excerpt", + "original_header": "Citation" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "workflows": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/workflow.cwl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "readme_url": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "contributing_guidelines": [ + { + "result": { + "value": "These guidelines were copied from [PychoPy](https://github.com/psychopy/psychopy/edit/dev/CONTRIBUTING.md)\n\n# Have you ever contributed to an Open Source project?\nYour first contribution can be a bit intimidating, but feel free to give it a try. If you get stuck, don't hesitate to ask for help in our [developer forum](https://discourse.psychopy.org/c/dev). This is also a good place to pitch your idea. Next up:\n* **I won't program it myself.** Please file a [GitHub issue](https://github.com/psychopy/psychopy/issues).\n* **I'd like to take a shot.** Read on to find out how!\n\n# How to contribute\nContributing to PsychoPy consists of four steps:\n1. Getting your own copy\n2. Making your changes\n3. Committing your changes\n4. Submitting a Pull Request\n\n## 1. Getting your own copy of the PsychoPy codebase\nTo be sure your improvements can easily be integrated, follow these steps:\n1. **Make a [fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) of the [PsychoPy repo](https://github.com/psychopy/psychopy).** This provides you with your own copy of the PsychoPy source code.\n2. **Inside your fork, make a new [branch](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-branches) for the feature you've got in mind.** If you'd like to fix a bug, base your new branch on the *release* branch. If you'd like to add a new feature, base it on the *dev* branch. We tend to name branches after the feature we're building. For example `olfactory_component`.\n3. **Clone your fork to your hard drive.** Next, switch to the new branch and you're all set up!\n\nLook [here](https://www.psychopy.org/developers/repository.html) to see how the PsychoPy repo is organized.\n\n## 2. Making your changes\nTo help you get started with modifying PsychoPy, we've got some [developer guides](https://www.psychopy.org/developers/index.html). To try out your modified PsychoPy, do a [developer's install](https://www.psychopy.org/download.html#developers-install).\n\n## 3. Committing your changes\nOnce you're happy with your changes, commit them to your GitHub repo. Please use the tags below in your commit and add an informative message.\n - **BF:** bug fix. For fixing bugs in the *release* branch.\n - **FF:** \u2018feature\u2019 fix. For fixing bugs in the *dev* branch.\n - **RF:** refactoring\n - **NF:** new feature\n - **ENH:** enhancement (to existing code, but don't worry too much about the difference between this and NF)\n - **DOC:** for all kinds of documentation related commits\n - **TEST:** for adding or changing tests\n\n## 4. File a Pull Request\nOnce you're done, it's time to add it to the central PsychoPy source code. File a [Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request) from your own fork and branch to the PsychoPy repo. Be sure to target the right branch in PsychoPy (*release* or *dev*). Thanks for contributing!\n", + "type": "File_dump" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/CONTRIBUTING.md" + } + ], + "ontologies": [ + { + "result": { + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/ontology.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "acknowledgement": [ + { + "result": { + "value": "This demonstration repo was created during the maSMP hackathon at [ZB MED](https://www.zbmed.de/en) sponsored by [NFDI4DataScience](https://www.nfdi4datascience.de). NFDI4DataScience is a consortium funded by the German Research Foundation (DFG), project number 460234259.\n", + "type": "Text_excerpt", + "original_header": "Acknowledgements" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "contact": [ + { + "result": { + "value": "Contact person responsible for maintaining a software component\n", + "type": "Text_excerpt", + "original_header": "Contact" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "contributors": [ + { + "result": { + "value": "Here could be a list of contributors to this software component\n", + "type": "Text_excerpt", + "original_header": "Contributors" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "documentation": [ + { + "result": { + "value": "Where to find additional documentation about a software component.\n", + "type": "Text_excerpt", + "original_header": "Documentation" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + }, + { + "result": { + "value": "For instructions on using OBA to create your API server, go to the [documentation](https://oba.readthedocs.io/en/latest/)\n", + "type": "Text_excerpt", + "original_header": "Related documentation" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "download": [ + { + "result": { + "value": "Download instructions included in the repository.\n", + "type": "Text_excerpt", + "original_header": "Download" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "faq": [ + { + "result": { + "value": "Frequently asked questions about a software component\n", + "type": "Text_excerpt", + "original_header": "FAQ" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "installation": [ + { + "result": { + "value": "A set of instructions that indicate how to install a target repository\n", + "type": "Text_excerpt", + "original_header": "Installation instructions" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "requirements": [ + { + "result": { + "value": "Pre-requisites and dependencies needed to execute a software component.\n", + "type": "Text_excerpt", + "original_header": "Requirements" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "run": [ + { + "result": { + "value": "There is no code in this repo that can be run.\n", + "type": "Text_excerpt", + "original_header": "Run" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "support": [ + { + "result": { + "value": "Guidelines and links of where to obtain support for a software component\n", + "type": "Text_excerpt", + "original_header": "Support" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + }, + { + "result": { + "value": "[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/OpenGeoscience/geonotebook)\n", + "type": "Text_excerpt", + "original_header": "Support channels" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "usage": [ + { + "result": { + "value": "Assumptions and considerations recorded by the authors when executing a software component, or examples on how to use it.", + "type": "Text_excerpt", + "original_header": "Usage examples" + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "identifier": [ + { + "result": { + "type": "Url", + "value": "https://zenodo.org/badge/latestdoi/450496579" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "full_title": [ + { + "result": { + "type": "String", + "value": "somef-demo-repo" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "related_documentation": [ + { + "result": { + "type": "Url", + "value": "https://oba.readthedocs.io/", + "format": "readthedocs" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "repository_status": [ + { + "result": { + "type": "Url", + "value": "https://www.repostatus.org/#active", + "description": "Active - The project has reached a stable, usable state and is being actively developed." + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "support_channels": [ + { + "result": { + "type": "Url", + "value": "https://gitter.im/OpenGeoscience/geonotebook" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "package_distribution": [ + { + "result": { + "type": "Url", + "value": "https://pypi.org/project/mapeathor/" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + }, + { + "result": { + "type": "Url", + "value": "https://pypi.org/project/mapeathor)/" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "logo": [ + { + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo//main/logo_directory/logo2.png" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "images": [ + { + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo//main/logo1.png" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ], + "related_papers": [ + { + "result": { + "type": "Url", + "value": "https://arxiv.org/abs/1802.08797" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/juanjemdIos/somef-demo-repo/main/README.md" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/api_responses/widoco_api_response.json b/src/somef_core/test/test_data/api_responses/widoco_api_response.json new file mode 100644 index 0000000..5d193d3 --- /dev/null +++ b/src/somef_core/test/test_data/api_responses/widoco_api_response.json @@ -0,0 +1,2779 @@ +{ + "somef_provenance": { + "somef_version": "0.9.12", + "somef_schema_version": "1.0.0", + "date": "2025-12-10 11:44:17" + }, + "code_repository": [ + { + "result": { + "value": "https://github.com/dgarijo/Widoco", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "https://github.com/dgarijo/Widoco", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "owner": [ + { + "result": { + "value": "dgarijo", + "type": "User" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "date_created": [ + { + "result": { + "value": "2013-07-15T15:51:51Z", + "type": "Date" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "2013-07-15", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "date_updated": [ + { + "result": { + "value": "2025-12-06T16:00:45Z", + "type": "Date" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "2025-01-31", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "license": [ + { + "result": { + "value": "https://api.github.com/licenses/apache-2.0", + "type": "License", + "name": "Apache License 2.0", + "url": "https://api.github.com/licenses/apache-2.0", + "spdx_id": "Apache-2.0" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {2016} {Daniel Garijo, Information Sciences Institute, USC.}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n", + "type": "File_dump", + "name": "Apache License 2.0", + "spdx_id": "Apache-2.0" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE" + }, + { + "result": { + "value": "Apache License 2.0", + "type": "License", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE", + "identifier": "https://spdx.org/licenses/Apache-2.0", + "spdx_id": "Apache-2.0" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "description": [ + { + "result": { + "value": "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + ], + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "value": "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n", + "type": "Text_excerpt", + "original_header": "Description", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "type": "Text_excerpt", + "value": "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. \n", + "original_header": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "confidence": 0.9336412604289143, + "technique": "supervised_classification", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "type": "Text_excerpt", + "value": "For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository.\n \n", + "original_header": "Current improvements" + }, + "confidence": 0.9682942149713352, + "technique": "supervised_classification", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "type": "Text_excerpt", + "value": "Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n", + "original_header": "Contribution guidelines" + }, + "confidence": 0.892416273463637, + "technique": "supervised_classification", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "name": [ + { + "result": { + "value": "Widoco", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Widoco", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "full_name": [ + { + "result": { + "value": "dgarijo/Widoco", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "issue_tracker": [ + { + "result": { + "value": "https://api.github.com/repos/dgarijo/Widoco/issues", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "https://github.com/dgarijo/Widoco/issues", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "forks_url": [ + { + "result": { + "value": "https://api.github.com/repos/dgarijo/Widoco/forks", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "stargazers_count": [ + { + "result": { + "value": 341, + "type": "Number" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "keywords": [ + { + "result": { + "value": "documentation, metadata, ontology, ontology-diagram, ontology-evaluation, wizard", + "type": "String" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": [ + "documentation", + "metadata", + "ontology", + "ontology-diagram", + "ontology-evaluation", + "wizard" + ], + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "forks_count": [ + { + "result": { + "value": 100, + "type": "Number" + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "download_url": [ + { + "result": { + "value": "https://github.com/dgarijo/Widoco/releases", + "type": "Url" + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "https://github.com/dgarijo/Widoco/releases", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "programming_languages": [ + { + "result": { + "value": "JavaScript", + "name": "JavaScript", + "type": "Programming_language", + "size": 1124896 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Java", + "name": "Java", + "type": "Programming_language", + "size": 594537 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "XSLT", + "name": "XSLT", + "type": "Programming_language", + "size": 226430 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "CSS", + "name": "CSS", + "type": "Programming_language", + "size": 84383 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "HTML", + "name": "HTML", + "type": "Programming_language", + "size": 35918 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "value": "Dockerfile", + "name": "Dockerfile", + "type": "Programming_language", + "size": 520 + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "name": "JavaScript", + "value": "JavaScript", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "name": "Java", + "value": "Java", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "name": "XSLT", + "value": "XSLT", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "name": "CSS", + "value": "CSS", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "name": "HTML", + "value": "HTML", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "name": "Dockerfile", + "value": "Dockerfile", + "type": "Programming_language" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "releases": [ + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/163195556", + "tag": "v1.4.25", + "name": "WiDOCO 1.4.25: Documentation fixes and new provenance flag", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO fixes documentation broken links, clarifies how to download Docker images and includes a new option for excluding the provenance page from documentation (thanks to @MikiDi) \r\n\r\n## What's Changed\r\n* Bump docker/build-push-action from 5.3.0 to 5.4.0 by @dependabot in https://github.com/dgarijo/Widoco/pull/709\r\n* CLI option to exclude provenance link by @MikiDi in https://github.com/dgarijo/Widoco/pull/710\r\n* Improved documentation (broken links)\r\n\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.24...v1.4.25", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.25", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.25", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.25", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/163195556", + "release_id": 163195556, + "date_created": "2024-06-30T09:43:24Z", + "date_published": "2024-06-30T09:48:00Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/176791751", + "name": "widoco-1.4.25-jar-with-dependencies_JDK-11.jar", + "content_size": 40858575, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.25/widoco-1.4.25-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-06-30T09:47:25Z", + "download_count": 2481 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/176791780", + "name": "widoco-1.4.25-jar-with-dependencies_JDK-14.jar", + "content_size": 40861516, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.25/widoco-1.4.25-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-06-30T09:47:40Z", + "download_count": 220 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/176791807", + "name": "widoco-1.4.25-jar-with-dependencies_JDK-17.jar", + "content_size": 40861591, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.25/widoco-1.4.25-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-06-30T09:47:48Z", + "download_count": 2576 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/153527742", + "tag": "v1.4.24", + "name": "WiDOCO 1.4.24: Hotfix for SWRL rules", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release introduces a hotfix for ontologies with SWRL rules and empty labels.\r\n\r\n## What's Changed\r\n* External Property Parser: Fix comparison to optional variable by @vChavezB in https://github.com/dgarijo/Widoco/pull/693\r\n* Develop by @dgarijo in https://github.com/dgarijo/Widoco/pull/701\r\n\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.23...v1.4.24", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.24", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.24", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.24", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/153527742", + "release_id": 153527742, + "date_created": "2024-04-30T15:04:14Z", + "date_published": "2024-04-30T15:12:35Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/165158401", + "name": "widoco-1.4.24-jar-with-dependencies_JDK-11.jar", + "content_size": 40858514, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.24/widoco-1.4.24-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-30T15:12:24Z", + "download_count": 99 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/165158392", + "name": "widoco-1.4.24-jar-with-dependencies_JDK-14.jar", + "content_size": 40861450, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.24/widoco-1.4.24-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-30T15:12:17Z", + "download_count": 37 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/165158374", + "name": "widoco-1.4.24-jar-with-dependencies_JDK-17.jar", + "content_size": 40861525, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.24/widoco-1.4.24-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-30T15:12:10Z", + "download_count": 314 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/150115431", + "tag": "v1.4.23", + "name": "WiDOCO 1.4.23: Bugfixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "Quick release for three minor bugs detected by @SirkoS:\r\n\r\n- Error in dark mode table\r\n- Markdown support when using the `uniteSections` flag\r\n- Content override when HTML sections were set up by hand.\r\n\r\n## What's Changed\r\n* bugfixes by @SirkoS in https://github.com/dgarijo/Widoco/pull/690\r\n* Merging latest master/develop by @dgarijo in https://github.com/dgarijo/Widoco/pull/691\r\n\r\n## New Contributors\r\n* @SirkoS made their first contribution in https://github.com/dgarijo/Widoco/pull/690\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.22...v1.4.23", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.23", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.23", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.23", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/150115431", + "release_id": 150115431, + "date_created": "2024-04-07T16:31:54Z", + "date_published": "2024-04-07T16:37:55Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160798750", + "name": "widoco-1.4.23-jar-with-dependencies_JDK-11.jar", + "content_size": 40858475, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.23/widoco-1.4.23-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-07T16:36:21Z", + "download_count": 170 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160798754", + "name": "widoco-1.4.23-jar-with-dependencies_JDK-14.jar", + "content_size": 40861411, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.23/widoco-1.4.23-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-07T16:36:30Z", + "download_count": 43 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160798761", + "name": "widoco-1.4.23-jar-with-dependencies_JDK-17.jar", + "content_size": 40861484, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.23/widoco-1.4.23-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-07T16:36:37Z", + "download_count": 161 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/149821484", + "tag": "v1.4.22", + "name": "WiDOCO 1.4.22: Dark mode and flexibility for loading references", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of Widoco adds a great dark mode by @vChavezB and some fixes to allow pointing to the code repo where a vocabulary is maintained, removing obsolete html annotations and allowing to load your own reference section from a config file. \r\n\r\n## What's Changed\r\n* Run widoco with unprivileged user in container by @janvlug in https://github.com/dgarijo/Widoco/pull/669\r\n* Fixed SWRL Toc by @vChavezB in https://github.com/dgarijo/Widoco/pull/670\r\n* Bump docker/metadata-action from 5.4.0 to 5.5.0 by @dependabot in https://github.com/dgarijo/Widoco/pull/673\r\n* Added darkmode by @vChavezB in https://github.com/dgarijo/Widoco/pull/672\r\n* Parsing external owl entities (direct/indirect imports) + individual facts with external owl entites by @vChavezB in https://github.com/dgarijo/Widoco/pull/668\r\n* Bump docker/metadata-action from 5.5.0 to 5.5.1 by @dependabot in https://github.com/dgarijo/Widoco/pull/678\r\n* feat: Considering owl:unionOf for rdfs:domain and rdfs:range by @Murloc6 in https://github.com/dgarijo/Widoco/pull/679\r\n* Allow loading local ontologies for imports by @vChavezB in https://github.com/dgarijo/Widoco/pull/674\r\n* Fix #618 by @dgarijo in https://github.com/dgarijo/Widoco/pull/685\r\n* fix(extraction): Do not force lower-case if URI do not have label by @Murloc6 in https://github.com/dgarijo/Widoco/pull/686\r\n* Develop by @dgarijo in https://github.com/dgarijo/Widoco/pull/687\r\n* version update by @dgarijo in https://github.com/dgarijo/Widoco/pull/689\r\n\r\n## New Contributors\r\n* @Murloc6 made their first contribution in https://github.com/dgarijo/Widoco/pull/679\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.21...v1.4.22", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.22", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.22", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.22", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/149821484", + "release_id": 149821484, + "date_created": "2024-04-04T17:40:30Z", + "date_published": "2024-04-04T17:48:33Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160331115", + "name": "widoco-1.4.22-jar-with-dependencies_JDK-11.jar", + "content_size": 40858426, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.22/widoco-1.4.22-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-04T17:56:01Z", + "download_count": 11 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160331165", + "name": "widoco-1.4.22-jar-with-dependencies_JDK-14.jar", + "content_size": 40861365, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.22/widoco-1.4.22-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-04T17:56:15Z", + "download_count": 7 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/160331135", + "name": "widoco-1.4.22-jar-with-dependencies_JDK-17.jar", + "content_size": 40861440, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.22/widoco-1.4.22-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2024-04-04T17:56:08Z", + "download_count": 1491 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/135444538", + "tag": "v1.4.21", + "name": "WiDOCO 1.4.21: Better support for rules and minor fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release introduces the following changes:\r\n* Better support for SWRL rules thanks to @vChavezB \r\n* Fix #658 problems displaying custom introduction sections\r\n* Improved documentation and README\r\n* Now the affiliation parenthesis and commas are more consistent for authors (#572)\r\n* Fixed a problem when using the flag `-confFile` making disappear the namespace declaration section\r\n\r\n## New Contributors\r\n* @MikiDi made their first contribution in https://github.com/dgarijo/Widoco/pull/644\r\n* @vChavezB made their first contribution in https://github.com/dgarijo/Widoco/pull/653\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.20...v1.4.21", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.21", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.21", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.21", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/135444538", + "release_id": 135444538, + "date_created": "2023-12-31T19:35:36Z", + "date_published": "2023-12-31T19:46:00Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/143178266", + "name": "widoco-1.4.21-jar-with-dependencies_JDK-11.jar", + "content_size": 40397382, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.21/widoco-1.4.21-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-12-31T19:50:32Z", + "download_count": 495 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/143178261", + "name": "widoco-1.4.21-jar-with-dependencies_JDK-14.jar", + "content_size": 40400218, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.21/widoco-1.4.21-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-12-31T19:50:24Z", + "download_count": 41 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/143178254", + "name": "widoco-1.4.21-jar-with-dependencies_JDK-17.jar", + "content_size": 40400273, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.21/widoco-1.4.21-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-12-31T19:50:19Z", + "download_count": 1112 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/119064737", + "tag": "v1.4.20", + "name": "WiDOCO 1.4.20: Increased Metadata support and many fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This new release addresses the issues listed below, and it updates the metadata guides:\r\n\r\n- Name is expanded and documented in table and guides (614).\r\n- DateRelease and dateModified overlap (fixed) (614)\r\n- Support for http and https in schema.org properties (before only https). This flexibility is to address potential mismatch properties.\r\n- Fixed Licensius integration issues (607)\r\n- Placed JSON-LD before than HTML in htaccess so we can import ontologies in the JSON-LD playground (i.e., from browser)\r\n- Support for extended ontologies added from the ontology metadata (with voaf:extends) (614)\r\n- Separated abstract from description. Used ontology description for the description section (544) \r\n- Imported ontologies have been added to the documentation table (614)\r\n- skos:editorialNote (592)\r\n- editorialNote is not added in guide (now added)\r\n- Added preferred metadata terms in checklist, and added examples for each (242)\r\n- Added dce and dct as elements and terms for dublin core.\r\n- Added support for:\r\n - pav:version (http://purl.org/pav/version) (versionInfo)\r\n - http://purl.org/dc/terms/hasVersion (versionInfo)\r\n - http://purl.org/pav/lastUpdatedOn (modified)\r\n - http://www.w3.org/2007/05/powder-s#describedBy (source)\r\n- Added support for logos (and guidelines to add them #497).\r\n- Fixed error: when saving properties, there are some nulls in publisher.\r\n- Added support for mod:status.\r\n- Added support for describedby (source)\r\n- Add editorialNote in metadata guide.\r\n- Add source in Widoco (ontology level). And load/save in properties. And form. And HTML.\r\n- Add seeAlso in Widoco (ontology level). And load/save in properties. And form. And HTML.\r\n- Explain how to run from code (#574)\r\n- add support for schema:creativeWorkStatus.\r\n- Sort NS table (#610)\r\n- Checked equivalentClass works correctly.\r\n- JFileChooser in GUI (602) (except a minor one for browsing folders)\r\n- Fix #605 about the main gui when saving withot the --rewriteAll option.\r\n- If multiple labels (skos:prefLabel, rdfs:label) are provided, just pick just one. #556 \r\n- Added funding and funder information \r\n- Intro section (new property) (#544, #612) \r\n- Intro: load it from properties file if available.\r\n- Supported serializations (new prop) \r\n- Fixed problem with funders.\r\n- Added tests.\r\n- Separate namespace declaration in a different html (#609)\r\n- isDefinedBy in data properties does not work well (#588)\r\n- Bug: properties extending annotation properties do not work (530) \r\n- Rules: add a new section + doc (#591)\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.20", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.20", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.20", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/119064737", + "release_id": 119064737, + "date_created": "2023-08-29T12:04:47Z", + "date_published": "2023-08-29T12:17:07Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/123609987", + "name": "widoco-1.4.20-jar-with-dependencies_JDK-11.jar", + "content_size": 41013250, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.20/widoco-1.4.20-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-08-29T12:24:28Z", + "download_count": 186 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/123610019", + "name": "widoco-1.4.20-jar-with-dependencies_JDK-14.jar", + "content_size": 41016047, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.20/widoco-1.4.20-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-08-29T12:24:33Z", + "download_count": 61 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/123610684", + "name": "widoco-1.4.20-jar-with-dependencies_JDK-17.jar", + "content_size": 41016100, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.20/widoco-1.4.20-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-08-29T12:27:11Z", + "download_count": 1662 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/105715227", + "tag": "v1.4.19", + "name": "WiDOCO 1.4.19: Small fixes on redirections and version", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This new release of WIDOCO:\r\n- Addresses a problem with the name of the files for the rdf/xml serialization (at times `.owl`, at time `.rdf`). Now it's always `.owl`.\r\n- Adds a small icon (RDF) to the documentation pages\r\n- Adds the version of the WIDOCO JAR explicitly with the command `--version`\r\n- OOPS! tests are now static, not requiring the service to work for the build to pass.\r\n\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.18...v1.4.19", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.19", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.19", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.19", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/105715227", + "release_id": 105715227, + "date_created": "2023-06-01T16:30:11Z", + "date_published": "2023-06-01T16:37:43Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/110831279", + "name": "widoco-1.4.19-jar-with-dependencies_JDK-11.jar", + "content_size": 41000835, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.19/widoco-1.4.19-jar-with-dependencies_JDK-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-06-01T16:42:00Z", + "download_count": 252 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/110831269", + "name": "widoco-1.4.19-jar-with-dependencies_JDK-14.jar", + "content_size": 41003361, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.19/widoco-1.4.19-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-06-01T16:41:55Z", + "download_count": 294 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/110831290", + "name": "widoco-1.4.19-jar-with-dependencies_JDK-17.jar", + "content_size": 41003414, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.19/widoco-1.4.19-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-06-01T16:42:08Z", + "download_count": 497 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/100962807", + "tag": "v1.4.18", + "name": "WIDOCO 1.4.18: Fix javascript issues", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version fixes:\r\n- Minor problems in the generated HTML.\r\n- Minor problems with mixed content in the javascript\r\n- Clarifies documentation on which fields Widoco adopts.\r\n\r\n## New Contributors\r\nThanks to: \r\n* @telecsur made their first contribution in https://github.com/dgarijo/Widoco/pull/517\r\n* @janvlug made their first contribution in https://github.com/dgarijo/Widoco/pull/538\r\n* @HanKruiger made their first contribution in https://github.com/dgarijo/Widoco/pull/540\r\n* @JohannesLipp made their first contribution in https://github.com/dgarijo/Widoco/pull/547\r\n* @ioggstream made their first contribution in https://github.com/dgarijo/Widoco/pull/561\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.17...v1.4.18", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.18", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.18", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.18", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/100962807", + "release_id": 100962807, + "date_created": "2023-04-21T15:46:00Z", + "date_published": "2023-04-26T14:08:45Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/105401521", + "name": "widoco-1.4.18-jar-with-dependencies-java-11.jar", + "content_size": 40526768, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.18/widoco-1.4.18-jar-with-dependencies-java-11.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-04-26T14:28:45Z", + "download_count": 85 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/105563934", + "name": "widoco-1.4.18-jar-with-dependencies_JDK-14.jar", + "content_size": 40529324, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.18/widoco-1.4.18-jar-with-dependencies_JDK-14.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-04-27T09:11:42Z", + "download_count": 28 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/105563920", + "name": "widoco-1.4.18-jar-with-dependencies_JDK-17.jar", + "content_size": 40529380, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.18/widoco-1.4.18-jar-with-dependencies_JDK-17.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2023-04-27T09:11:32Z", + "download_count": 66 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "tag": "v1.4.17", + "name": "WIDOCO 1.4.17: Update OOPS! Web service. GitHub actions", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version fixes OOPS! (newest URL) and sets up GitHub actions so users with different versions of Java can use Widoco.\r\n\r\n## What's Changed\r\n* update readme and pom with proper versions by @dgarijo in https://github.com/dgarijo/Widoco/pull/502\r\n* switch import fonts to always use https scheme by @renefritze in https://github.com/dgarijo/Widoco/pull/509\r\n* [ci] setup gh actions + dependabot by @renefritze in https://github.com/dgarijo/Widoco/pull/507\r\n* Github actions set up by @renefritze by @dgarijo in https://github.com/dgarijo/Widoco/pull/512\r\n\r\n## New Contributors\r\n* @renefritze made their first contribution in https://github.com/dgarijo/Widoco/pull/509\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.16...v1.4.17", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.17", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.17", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.17", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "release_id": 64724790, + "date_created": "2022-04-19T10:57:14Z", + "date_published": "2022-04-19T11:10:33Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/62988840", + "name": "java-11-widoco-1.4.17-jar-with-dependencies.jar", + "content_size": 40505030, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.17/java-11-widoco-1.4.17-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2022-04-19T11:07:47Z", + "download_count": 2664 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/62988900", + "name": "java-14-widoco-1.4.17-jar-with-dependencies.jar", + "content_size": 40507499, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.17/java-14-widoco-1.4.17-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2022-04-19T11:08:34Z", + "download_count": 214 + }, + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/62988955", + "name": "java-17-widoco-1.4.17-jar-with-dependencies.jar", + "content_size": 40507555, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.17/java-17-widoco-1.4.17-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2022-04-19T11:09:22Z", + "download_count": 1624 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "tag": "v1.4.16", + "name": "WIDOCO 1.4.16: Support for German and Dutch", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO includes support for German and Dutch (thanks to Flores Bakker), extraction of metadata from local authors and organizations URIs (if you describe authors and their organizations in your ontology, WIDOCO will automatically detect it) and additional support for adding images in your documentation.\r\n \r\n## What's Changed\r\n* Fix/duplicate namespace declarations by @pmcb55 in https://github.com/dgarijo/Widoco/pull/471\r\n* Only show legend entries if relevant by @pmcb55 in https://github.com/dgarijo/Widoco/pull/472\r\n* Dockerize project by @ccamel in https://github.com/dgarijo/Widoco/pull/479\r\n* Support for adding images with GUI by @dgarijo in https://github.com/dgarijo/Widoco/pull/492\r\n* Fix #262 by @dgarijo in https://github.com/dgarijo/Widoco/pull/493\r\n* German translation by @JohnnyMoonlight in https://github.com/dgarijo/Widoco/pull/494\r\n* Support for it and de by @dgarijo in https://github.com/dgarijo/Widoco/pull/495\r\n* Fix #498 by @engapa in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n## New Contributors\r\n* @ccamel made their first contribution in https://github.com/dgarijo/Widoco/pull/479\r\n* @JohnnyMoonlight made their first contribution in https://github.com/dgarijo/Widoco/pull/494\r\n* @engapa made their first contribution in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.15...v1.4.16", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.16", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.16", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.16", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "release_id": 62144298, + "date_created": "2022-03-17T21:38:26Z", + "date_published": "2022-03-17T22:13:15Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/59812154", + "name": "widoco-1.4.16-jar-with-dependencies.jar", + "content_size": 40504976, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.16/widoco-1.4.16-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2022-03-17T22:11:40Z", + "download_count": 495 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/45273016", + "tag": "v1.4.15", + "name": "WIDOCO 1.4.15: Major bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release addresses the following problems:\r\n- fixed return types for jsonld and rdf (#454)\r\n- fixed small caps issue for case sensitivity files in Unix (#455)\r\n- fix wrong metadata in prefix (#453) \r\n- Incorporated previous prereleases fixes.\r\n\r\nAll bugs fixed in this release can be found [here](https://github.com/dgarijo/Widoco/milestone/2?closed=1)", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.15", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.15", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.15", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/45273016", + "release_id": 45273016, + "date_created": "2021-06-26T11:29:58Z", + "date_published": "2021-06-26T11:39:10Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/40200251", + "name": "widoco-1.4.15-jar-with-dependencies.jar", + "content_size": 39590551, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.15/widoco-1.4.15-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2021-07-13T08:45:02Z", + "download_count": 1787 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/35216684", + "tag": "v1.4.15_1", + "name": "WIDOCO 1.4.15_1 (pre-release): Namespace prefixes fixes and WebVowl update", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This pre-release fixes issues regarding namespace prefixes (now they will be rad directly from the ontology instead of using LODE); it updates WebVOWL to the latest version (which let's you change the settings in your visualization)\r\n\r\nMore information on the addressed issues can be seen in: https://github.com/dgarijo/Widoco/milestone/2?closed=1", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.15_1", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.15_1", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.15_1", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/35216684", + "release_id": 35216684, + "date_created": "2020-12-14T04:07:24Z", + "date_published": "2020-12-14T04:18:58Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/29515905", + "name": "widoco-1.4.15-jar-with-dependencies.jar", + "content_size": 40032888, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.15_1/widoco-1.4.15-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2020-12-14T04:14:32Z", + "download_count": 1935 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/28719056", + "tag": "v1.4.15_0", + "name": "WIDOCO 1.4.15 (pre-release): Bug fixes and FAQ", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "(This is a pre-relase. For more information about the next release see https://github.com/dgarijo/Widoco/milestone/2)\r\nThis pre-release of WIDOCO fixes some bugs and adds a FAQ for common questions posted as issues. In particular, this solves:\r\n- External links will now open in another window instead of appearing dotted.\r\n- Fixed issue that made the index not be generated when including all the sections in a single html.\r\n- Added a FAQ explaining why by default the documentation cannot be seen locally.\r\n- Added a FAQ regarding how to use markdown on class definitions.\r\n- Error with a missing path when the CLI was run, which resulted in the /sections folder not being generated.\r\n- Fixed a typo in acknowledgments \r\n- Fixed typo in schema.org snippet.\r\n- Fixed a few URLs from http -> https", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.15_0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.15_0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.15_0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/28719056", + "release_id": 28719056, + "date_created": "2020-07-19T22:55:20Z", + "date_published": "2020-07-19T23:11:42Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/23035620", + "name": "widoco-1.4.15-jar-with-dependencies.jar", + "content_size": 39372460, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.15_0/widoco-1.4.15-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2020-07-19T23:11:10Z", + "download_count": 83 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/26848705", + "tag": "v1.4.14", + "name": "WIDOCO 1.4.14: Multiple updates and bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO updates some of the web services used:\r\n * Updated a comprehensive --help command.\r\n * Reviewed metadata properties (added incompatibleWith)\r\n * Removed JENA dependencies (now only OWLAPI is used)\r\n * Unified logging (now only SLF4J is used).\r\n * Fixed pointers in WIDOCO guidelines.\r\n * Updated OOPS! webservice call.\r\n * Fixed invalid ttl file when generating the provenance of a documentation.", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.14", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.14", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.14", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/26848705", + "release_id": 26848705, + "date_created": "2020-05-25T03:55:27Z", + "date_published": "2020-05-25T04:02:40Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/21025783", + "name": "widoco-1.4.14-jar-with-dependencies.jar", + "content_size": 39384905, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.14/widoco-1.4.14-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2020-05-25T04:02:00Z", + "download_count": 2175 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/22775882", + "tag": "v1.4.13", + "name": "WIDOCO 1.4.13: Linking evaluation in documentation", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO removes a few of unused dependencies and, if desired, shows a link to the OOPS! evaluation generated in the documentation. Before, this link had to be added manually. \r\n\r\nThanks to @HaydarAk for the suggestions on how to show it in the main page.\r\n\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.13", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.13", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.13", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/22775882", + "release_id": 22775882, + "date_created": "2020-01-12T22:19:15Z", + "date_published": "2020-01-12T22:25:11Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/17295468", + "name": "widoco-1.4.13-jar-with-dependencies.jar", + "content_size": 41627773, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.13/widoco-1.4.13-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2020-01-12T22:22:32Z", + "download_count": 20613 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/21002818", + "tag": "v1.4.12", + "name": "WIDOCO 1.4.12: Big fixes and new configurations", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO addresses the following issues (thanks to @pmcb55 for his contributions!!)\r\n * #354: The page would display centered in the visualization instead of the element loaded.\r\n * #362: Upgraded to latest version of OWL API\r\n * #361: Allowed adding a \"-uniteAllSections\" flag that will print all sections on the same document. Hence, dynamic loading will be removed.\r\n * Tidying up PROV rendering.\r\n * Small typo fixes in the default html ", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.12", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.12", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.12", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/21002818", + "release_id": 21002818, + "date_created": "2019-10-27T03:41:36Z", + "date_published": "2019-10-27T03:56:44Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/15756430", + "name": "widoco-1.4.12-jar-with-dependencies.jar", + "content_size": 41626814, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.12/widoco-1.4.12-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2019-10-27T03:56:00Z", + "download_count": 198 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/17596778", + "tag": "v1.4.11", + "name": "WIDOCO 1.4.11: Better logging and bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO integrates the pull requests from @seralf to improve logging and simplify dependencies.\r\nIn addition, it addresses the following issues:\r\n * #344: Now double \"#\" errors have been removed from changelog.\r\n * #350: Fixed an issue in which the references would overwrite the main section ", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.11", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.11", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.11", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/17596778", + "release_id": 17596778, + "date_created": "2019-05-26T23:51:42Z", + "date_published": "2019-05-26T23:55:13Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/12880234", + "name": "widoco-1.4.11-jar-with-dependencies.jar", + "content_size": 41614957, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.11/widoco-1.4.11-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2019-05-26T23:53:22Z", + "download_count": 413 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/17029600", + "tag": "v1.4.10", + "name": "WIDOCO 1.4.10: Pull requests, updates and bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO incorporates pull requests from @seralf and @jgeluk (updating to the latest version of WebVowl) and fixes the following issues:\r\n* #333 Now if there is an error in one of the imports the application will continue running instead of failing.\r\n* #217 Now the changelog can be expanded and collapsed, which makes it easier to navigate\r\n* #313 A link will be added in the index page if provided in the config file (using contextURI=\"YOUR URL\")\r\n* #339 Now WIDOCO will generate the folders four your htaccess file as well.\r\n\r\nIn addition, now the base encoding is UTF-8.", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.10", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.10", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.10", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/17029600", + "release_id": 17029600, + "date_created": "2019-04-29T00:26:07Z", + "date_published": "2019-04-29T00:31:54Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/12283704", + "name": "widoco-1.4.10-jar-with-dependencies.jar", + "content_size": 41613738, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.10/widoco-1.4.10-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2019-04-29T00:31:17Z", + "download_count": 58 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/15737608", + "tag": "v1.4.9", + "name": "WIDOCO 1.4.9: Supporting schema.org", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO addresses the following:\r\n* #274: Now WIDOCO will include the domain and range if you use schema:domainIncludes and schema:rangeIncludes to declare it in your object properties or data properties with . Note that WIDOCO still does not support plain rdf:Property.\r\n* Reduced the level of logging", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.9", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.9", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.9", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/15737608", + "release_id": 15737608, + "date_created": "2019-02-24T00:23:18Z", + "date_published": "2019-02-24T00:30:33Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/11213134", + "name": "widoco-1.4.9-jar-with-dependencies.jar", + "content_size": 41691275, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.9/widoco-1.4.9-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2019-02-24T00:28:43Z", + "download_count": 146 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/15474861", + "tag": "v1.4.8", + "name": "WIDOCO 1.4.8: Logging and automated citation", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release of WIDOCO includes:\r\n* Fixes from @jgeluk to do proper logging.\r\n* Fix #264: now an automated citation will be produced for your ontology by default (if the appropriate metadata is there: creators, revision, and URL (this version)\r\n* JenaCatalogIRIMapper now supports Jena's ont-policy.rdf file to resolve imports with local files\r\n* Fixed #321, now WIDOCO uses a more recent version of OWL API \r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.8", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.8", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.8", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/15474861", + "release_id": 15474861, + "date_created": "2019-02-11T03:30:12Z", + "date_published": "2019-02-11T03:38:13Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/11023656", + "name": "widoco-1.4.8-jar-with-dependencies.jar", + "content_size": 41511458, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.8/widoco-1.4.8-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2019-02-11T03:32:51Z", + "download_count": 56 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/13944540", + "tag": "v1.4.7", + "name": "WIDOCO 1.4.7: Dependency and bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release of WIDOCO fixes the following issues:\r\n* #305: Now when you launch WIDOCO without parameters, the console will also show a description of the tool and will explain how to run it. \r\n* #309 Removed the absolute layout dependency that prevented WIDOCO JAR from being run.\r\n* #311 Now the publisher will show on the GUI correctly (before it would only if it had a URL)\r\n* #314: Added an html tag around the external sections so the browser won't complain\r\n* #316 Fixed the generation of the table of contents so \"back to TOC\" wouldn't appear\r\n* #317 Fixed the GUI so the \"Imported ontologies\" label appears as imported and not \"extended\"\r\nIt also removes the restlet dependency, which had a vulnerability and was not used anymore.", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.7", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.7", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.7", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/13944540", + "release_id": 13944540, + "date_created": "2018-11-12T03:27:02Z", + "date_published": "2018-11-12T03:42:29Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/9650269", + "name": "widoco-1.4.7-jar-with-dependencies.jar", + "content_size": 41317020, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.7/widoco-1.4.7-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-11-12T03:37:07Z", + "download_count": 187 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/13019723", + "tag": "v1.4.6", + "name": "WIDOCO 1.4.6: Tutorial and bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO includes the following updates:\r\n* Updated the OWL2Vowl library to the latest version (old library was producing errors in some ontologies)\r\n* Included a tutorial (http://dgarijo.github.io/Widoco/doc/tutorial/) describing the GUI step by step and all its functionality\r\n* Added support for selecting ontologies in JSON\r\n* Added contributing guidelines into readme.md\r\n* Fixed namespaces when selecting documentation in several languages\r\n* Now it's possible to edit the rewrite base path in the .htaccess file.\r\n* Fixed a typo in the .htaccess for serving json\r\n* Fixed an encoding problem when showing french labels.\r\n* @kartgk fixed an error with the import closure of ontologies (in case not all imports of imported ontologies wanted to be displayed)\r\n* Added the correct version numbers to pom file.\r\n* Fixed an issue in lang cs that made the table of namespaces not to show correctly", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.6", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.6", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.6", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/13019723", + "release_id": 13019723, + "date_created": "2018-09-21T08:03:14Z", + "date_published": "2018-09-21T08:19:40Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/8774684", + "name": "widoco-1.4.6-jar-with-dependencies.jar", + "content_size": 42009392, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.6/widoco-1.4.6-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-09-21T08:08:43Z", + "download_count": 552 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/12049594", + "tag": "v1.4.5", + "name": "WIDOCO 1.4.5: Updated WebVowl and support for Czech", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO includes the following updates:\r\n* Updated webVowl to version 1.1.2 (latest)\r\n* Allowed disabling showing ontology serializations (-doNotDisplaySerializations flag). Both in the console and GUI\r\n* Added support for Czech localization (also in GUI)\r\n\r\nThanks to Petr Kremen for contributing with the Czech localization", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.5", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.5", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.5", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/12049594", + "release_id": 12049594, + "date_created": "2018-07-23T07:15:14Z", + "date_published": "2018-07-23T07:23:58Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/7970893", + "name": "widoco-1.4.5-jar-with-dependencies.jar", + "content_size": 43008958, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.5/widoco-1.4.5-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-07-23T07:22:14Z", + "download_count": 220 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/11300894", + "tag": "v1.4.4", + "name": "WIDOCO 1.4.4: Added support for Google Analytics", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO allows to add a Google Analytics code to track the traffic received in one of the pages. WIDOCO assumes you have a UA code. You can use it on the GUI, through a config file or in the command line by adding `-analytics yourcode`\r\n\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.4", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.4", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.4", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/11300894", + "release_id": 11300894, + "date_created": "2018-06-04T01:12:31Z", + "date_published": "2018-06-04T01:17:34Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/7395302", + "name": "widoco-1.4.4-jar-with-dependencies.jar", + "content_size": 42927288, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.4/widoco-1.4.4-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-06-04T01:16:33Z", + "download_count": 61 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/10556972", + "tag": "v1.4.3", + "name": "WIDOCO 1.4.3: Bug Fixes and support for french", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release fixes the following issues:\r\n* Added support for french (thanks to Maxime Lefrancois)\r\n* When imported ontologies had characters like \"<\" they were not showing.\r\n* Added JSON-LD serialization for ontologies automatically\r\n* When annotation properties have blank nodes, they will now be ignored instead of failing\r\n* Updated contributor list\r\n* Blank nodes are now absent from the provenance page.\r\n* Fixed default language when restarting WIDOCO.\r\n* Fixed the language form (now french can be selected, and it has the proper icons)\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.3", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.3", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.3", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/10556972", + "release_id": 10556972, + "date_created": "2018-04-16T05:17:23Z", + "date_published": "2018-04-16T05:23:25Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/6856085", + "name": "widoco-1.4.3-jar-with-dependencies.jar", + "content_size": 42926579, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.3/widoco-1.4.3-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-04-16T05:22:47Z", + "download_count": 96 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/9846306", + "tag": "v1.4.2", + "name": "WIDOCO 1.4.2: Small fixes and merged contributions", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release includes the latest contributions to the project:\r\n* Fixes in HTML\r\n* Fixes in how OOPS! is called\r\nAlso, now the license name is the URI if no name is provided (and URI is) instead of \"license name goes here\", and the java encoding has been included in the pom file to prevent UTF-8 errors in compilation.", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.2", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.2", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.2", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/9846306", + "release_id": 9846306, + "date_created": "2018-02-27T02:55:24Z", + "date_published": "2018-02-27T03:02:50Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/6336641", + "name": "widoco-1.4.2-jar-with-dependencies.jar", + "content_size": 42914602, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.2/widoco-1.4.2-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2018-02-27T02:58:44Z", + "download_count": 231 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/6527938", + "tag": "v1.4.1", + "name": "WIDOCO 1.4.1: Metadata support and major bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "WIDOCO now will comply with most of the terms listed in https://w3id.org/widoco/bestPractices. A few of them are still unsopported (e.g., rdfs:seeAlso) and will be added in next releases.\r\n\r\nIn this version, I have added support for all the deprecation terms in LODE, as well as support for skos:prefLabel and better recognition of some of the terms when the range can be a String or a resource.\r\n\r\nChanges:\r\n* Now the examples have a \"pre\" label, so if they include rdf text or json text they show properly.\r\n* A pointer to the guidelines has been added in the interface\r\n* When invoking the program using command line, the default behavior is to load the properties from the ontology. Only if a config file is provided, the properties won't be loaded. There is still a flag, which I have preferred to leave for possible legacy issues.\r\n* Markup is now recognized in all sections\r\n* The diagram is now optional (by default it was always produced in older versions)\r\n* This release also includes a doc folder with guidelines on the metadata properties to use, a benchmark of ontologies used for testing, a gallery with what WIDOCO can accomplish and a summary of projects that have adopted WIDOCO.\r\n\r\nBug fixes: \r\n* Changed the pom file with another plugin for creating the JAR, because some of the RIO parsers were not creating the appropriate serializations of the ontology.\r\n* Added robustness when the changelog was created. If a wrong URI is provided, then the changelog will not be created.\r\n* Changed how the ontology is chosen so there won't be errors in MAC systems.\r\n* Fixed some of the language tags.\r\n* Polished some errors related to the interface.", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.1", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.1", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.1", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/6527938", + "release_id": 6527938, + "date_created": "2017-05-28T10:17:58Z", + "date_published": "2017-05-28T18:46:39Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/3978689", + "name": "widoco-1.4.1-jar-with-dependencies.jar", + "content_size": 42914378, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.1/widoco-1.4.1-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2017-05-28T18:36:04Z", + "download_count": 386 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/6390471", + "tag": "v1.4.0", + "name": "WIDOCO 1.4.0: Inline visualization diagrams", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release removes the external dependency to WebVowl, and creates a visualization that can be seen in the ontology document itself (overview section). In addition, the following changes have been made:\r\n * Migrated the framework to use a recent version of OWL API (hence the size of the JAR)\r\n * Bug fixes in meta data (more to come in future releases)\r\n * Made WIDOCO more robust to errors\r\n * Published a benchmark of ontologies used to test WIDOCO. If you want us to try a new one, just open an issue!\r\n * Published a draft of the best practices for ontology annotation (currently under work). These are meant\r\n * Published a showcase gallery with examples of WIDOCO's features\r\n * Published a report on the known usages by WIDOCO. \r\n\r\n![webvowl](https://cloud.githubusercontent.com/assets/1520666/26068984/54eff946-3954-11e7-81b8-c72db0bd93bb.png)\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/6390471", + "release_id": 6390471, + "date_created": "2017-05-13T23:26:12Z", + "date_published": "2017-05-15T16:53:34Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/3879303", + "name": "widoco-1.4.0-jar-with-dependencies.jar", + "content_size": 41119076, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.4.0/widoco-1.4.0-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2017-05-15T16:46:54Z", + "download_count": 28 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/5951267", + "tag": "v1.3.1", + "name": "Widoco 1.3.1: Bug fixes and metadata enrichment", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release fixes several issues and extends LODE to accept more metadata options for defining terms and adding examples.\r\n* Fixed an issue with the changelog that produced an empty bullet when the domain or range of a property was an union or intersection.\r\n* Added tests with different ontologies that help inspecting whether a new change leads to errors or not.\r\n* Extended LODE to accept: prov:definition, vann:example, obo:definition (with the appropriate class name), obo:usageExample, vaem:rationale, skos:definition and terms:source.\r\n* Extended Widoco to accept terms:bibliographicCitation, bibo:status, bibo:doi and owl:backwardsCompatibleWith\r\n* If an error is produced while generating the changelog or the evaluation reports, the section is not generated. Before, an empty section would remain.\r\n* Fixed table of contents not being translated.\r\n* When generating the documentation of an ontology, if it imports another ontology that cannot be imported for any reason, Widoco will ignore the import instead of failing.\r\n* Added the possibility to ignore namedIndividuals when generating the documentation through console.\r\n\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.3.1", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.3.1", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.3.1", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/5951267", + "release_id": 5951267, + "date_created": "2017-04-03T00:33:14Z", + "date_published": "2017-04-03T00:48:48Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/3558233", + "name": "widoco-1.3.1-jar-with-dependencies.jar", + "content_size": 15577816, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.3.1/widoco-1.3.1-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2017-04-04T03:00:37Z", + "download_count": 34 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/5659212", + "tag": "v1.3.0", + "name": "Widoco 1.3.0: Automated changelog section", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of Widoco creates an automated changelog section of your ontology. For all classes, properties and data properties, Widoco will calculate the new changes, additions and deletions and present them in a human-readable manner. In order to benefit from this feature, you just have to annotate your ontology with the URI of the previous version. You can use owl:priorVersion, dc:replaces or prov:wasRevisionOf to annotate your ontology (Widoco will only consider one file to compare against).\r\n\r\nAdditional improvements:\r\n* RDF-a annotations are replaced with JSON-LD snippets. The page is just annotated with schema.org. The rdf-a annotations made it difficult to maintain, and the structured extraction tool provided by Google did not work. With the JSON-LD snippet everything is clearer. The provenance of the page itself is published separately.\r\n* Now it is possible to generate ONLY the cross reference section of an ontology.\r\n* Bug fix that led to errors when opening some ontologies like OBI\r\n\r\nOverview sample of the changelog:\r\n![overview](https://cloud.githubusercontent.com/assets/1520666/23640611/ac4407f6-02a3-11e7-8a88-b597ba740721.png)\r\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.3.0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.3.0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.3.0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/5659212", + "release_id": 5659212, + "date_created": "2017-03-07T03:06:28Z", + "date_published": "2017-03-07T03:17:36Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/3335677", + "name": "widoco-1.3.0-jar-with-dependencies.jar", + "content_size": 15423937, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.3.0/widoco-1.3.0-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2017-03-07T03:16:43Z", + "download_count": 36 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/4659138", + "tag": "v1.2.3", + "name": "Widoco 1.2.3: [Bug fix] Licensius is optional", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "The Licensius web service has been unstable lately. This led to long waits from the server, even with a timer on the request. Therefore retrieving the license using this service is now optional and loading metadata properties from the ontology is faster.\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.2.3", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.2.3", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.2.3", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/4659138", + "release_id": 4659138, + "date_created": "2016-11-15T03:11:37Z", + "date_published": "2016-11-15T03:17:26Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/2645844", + "name": "widoco-1.2.3-jar-with-dependencies.jar", + "content_size": 15411854, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.2.3/widoco-1.2.3-jar-with-dependencies.jar", + "encoding_format": "application/x-java-archive", + "upload_date": "2016-11-15T03:16:18Z", + "download_count": 91 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3832172", + "tag": "v1.2.2", + "name": "Widoco 1.2.2: Major bug fixes and improvements", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version fixes the following issues/improvements:\n- 188: lang separator doesn't work on unix systems. Changed \";\" to \"-\" as separator\n- 189: return a non-zero value if there are problems generating the doc\n- 151: text area in the table should be bigger \n- 177: Ability to provide authors institution URI in the config \n- 155: allow possibility of adding Zenodo URI (DOI) \n- 132: could improve placeholder text\n- 174: Dynamic sections \n- 170: Check why isDefinedBy is not recognized sometimes\n- 171: Separate configuration from vocabulary metadata \n\nIn addition, I have fixed the custom style CSS, saving the publisher in the config file, producing an alt in images to avoid broken images when no connection is available and issues with the consistency in sections and back to toc titles.\n\nFinally, the toc will be now dynamic, so it will get updated if new headers with class \"list\" are added to the document.\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.2.2", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.2.2", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.2.2", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3832172", + "release_id": 3832172, + "date_created": "2016-08-07T20:39:13Z", + "date_published": "2016-08-07T20:49:16Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/2111104", + "name": "widoco-1.2.2-jar-with-dependencies.jar", + "content_size": 15390961, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.2.2/widoco-1.2.2-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-08-08T08:22:33Z", + "download_count": 39 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3701886", + "tag": "v1.2.1", + "name": "Widoco 1.2.1: Interface bug fixes", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "In this release a couple of bugs have been fixed.\nFirst, a bug that froze the program after hitting the \"back\" button, once the ontology properties had been loaded.\nAnother bug fix is that now \"publisher\" will not appear if it's not filled in the .properties file.\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.2.1", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.2.1", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.2.1", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3701886", + "release_id": 3701886, + "date_created": "2016-07-20T16:54:43Z", + "date_published": "2016-07-20T16:58:10Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/2021317", + "name": "widoco-1.2.1-jar-with-dependencies.jar", + "content_size": 15363104, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.2.1/widoco-1.2.1-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-07-20T16:57:51Z", + "download_count": 27 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3683077", + "tag": "v1.2.0", + "name": "Widoco 1.2.0: Extended metadata enrichment", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version automatically extracts the properties \"publisher\" and \"versionIRI\" from the ontology. In addition, it adds a link to webVowl and fixes some minor issues.\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.2.0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.2.0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.2.0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3683077", + "release_id": 3683077, + "date_created": "2016-07-18T16:47:41Z", + "date_published": "2016-07-18T16:52:10Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/2007860", + "name": "widoco-1.2.0-jar-with-dependencies.jar", + "content_size": 15363881, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.2.0/widoco-1.2.0-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-07-18T16:51:55Z", + "download_count": 15 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3673322", + "tag": "v1.1.1", + "name": "Widoco1.1.1: Integration with Licensius is back online", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release contains the time outs for using Licensius (for retrieveing license names from the ontology) and OOPS! (for evaluation)\nIn addition, it also fixes some small issued with content negotiation when loading Prot\u00e9g\u00e9. By default, the .htaccess file will serve rdf/xml when asking for \\* / \\* and turtle when asking for text/*\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.1.1", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.1.1", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.1.1", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3673322", + "release_id": 3673322, + "date_created": "2016-07-16T15:53:39Z", + "date_published": "2016-07-16T15:59:49Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/2000539", + "name": "widoco-1.1.1-jar-with-dependencies.jar", + "content_size": 15358279, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.1.1/widoco-1.1.1-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-07-16T16:09:51Z", + "download_count": 16 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3599226", + "tag": "v1.1.0", + "name": "Content negotiation bundle", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "Now Widoco can create a content negotiation bundle that helps you deploy your vocabulary on your server. In addition, now different serializations of a vocabulary are saved locally, in order to facilitate users pointing to them.\n\nNote: due to time outs in Licensius, it is disabled in this version\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.1.0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.1.0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.1.0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3599226", + "release_id": 3599226, + "date_created": "2016-07-06T15:57:53Z", + "date_published": "2016-07-06T16:01:06Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/1950415", + "name": "widoco-1.1.0-jar-with-dependencies.jar", + "content_size": 15358060, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.1.0/widoco-1.1.0-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-07-06T16:00:40Z", + "download_count": 18 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + }, + { + "result": { + "type": "Release", + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/3263232", + "tag": "v1.0.0", + "name": "First stable release of Widoco", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This release fixes multiple bugs from the earlier release, and allows customizing a label on the side with the current status of the document.\n\nThis version also improves how an ontology is loaded, applying content negotiation when necessary.\n", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.0.0", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.0.0", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.0.0", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/3263232", + "release_id": 3263232, + "date_created": "2016-05-19T16:43:03Z", + "date_published": "2016-05-19T16:49:39Z", + "assets": [ + { + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/assets/1712555", + "name": "widoco-1.0.0-jar-with-dependencies.jar", + "content_size": 15354399, + "content_url": "https://github.com/dgarijo/Widoco/releases/download/v1.0.0/widoco-1.0.0-jar-with-dependencies.jar", + "encoding_format": "application/octet-stream", + "upload_date": "2016-05-19T16:47:08Z", + "download_count": 23 + } + ] + }, + "confidence": 1, + "technique": "GitHub_API" + } + ], + "has_build_file": [ + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/Dockerfile", + "type": "Url", + "format": "dockerfile" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/Dockerfile" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml", + "type": "Url", + "format": "pom.xml" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + } + ], + "citation": [ + { + "result": { + "value": "title: \"WIDOCO: A Wizard for documenting ontologies\"\nlicense: Apache-2.0\nauthors:\n - family-names: Garijo\n given-names: Daniel\n orcid: \"http://orcid.org/0000-0003-0454-7145\"\ncff-version: 1.2.0\nmessage: \"If you use this software, please cite both the article from preferred-citation and the software itself.\"\npreferred-citation:\n authors:\n - family-names: Garijo\n given-names: Daniel\n title: \"WIDOCO: A wizard for documenting ontologies\"\n type: article\n year: 2017\n doi: 10.1007/978-3-319-68204-4_9\nidentifiers:\n - description: \"Collection of archived snapshots for WIDOCO\"\n type: doi\n value: 10.5281/zenodo.591294\n", + "type": "File_dump", + "identifier": [ + { + "description": "Collection of archived snapshots for WIDOCO", + "type": "doi", + "value": "10.5281/zenodo.591294" + } + ], + "author": [ + { + "type": "Agent", + "name": "Daniel Garijo", + "family_name": "Garijo", + "given_name": "Daniel", + "url": "http://orcid.org/0000-0003-0454-7145" + } + ], + "title": "WIDOCO: A Wizard for documenting ontologies", + "url": "https://doi.org/10.5281/zenodo.591294", + "doi": "10.1007/978-3-319-68204-4_9", + "format": "cff", + "datePublished": "2017" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/CITATION.cff" + }, + { + "result": { + "value": "WIDOCO: a wizard for documenting ontologies", + "title": "WIDOCO: a wizard for documenting ontologies", + "type": "Scholarly_article", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "date_published": "2017", + "doi": "10.1007/978-3-319-68204-4_9" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "value": "@inproceedings{garijo2017widoco,\n url = {http://dgarijo.com/papers/widoco-iswc2017.pdf},\n funding = {USNSF ICER-1541029, NIH 1R01GM117097-01},\n doi = {10.1007/978-3-319-68204-4_9},\n organization = {Springer, Cham},\n year = {2017},\n pages = {94--102},\n booktitle = {International Semantic Web Conference},\n author = {Garijo, Daniel},\n title = {WIDOCO: a wizard for documenting ontologies},\n}", + "type": "Text_excerpt", + "format": "bibtex", + "doi": "10.1007/978-3-319-68204-4_9", + "title": "WIDOCO: a wizard for documenting ontologies", + "author": "Garijo, Daniel", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "package_id": [ + { + "result": { + "value": "es.oeg.widoco", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + } + ], + "version": [ + { + "result": { + "value": "1.4.26", + "type": "Release" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "v1.4.25", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "requirements": [ + { + "result": { + "value": "org.apache.maven.maven-model", + "name": "maven-model", + "version": "3.9.0", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "org.jsoup.jsoup", + "name": "jsoup", + "version": "1.17.2", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "com.github.VisualDataWeb.OWL2VOWL", + "name": "OWL2VOWL", + "version": "0.3.5", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "org.slf4j.slf4j-api", + "name": "slf4j-api", + "version": "1.7.30", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "org.slf4j.slf4j-simple", + "name": "slf4j-simple", + "version": "1.7.30", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "net.sf.saxon.Saxon-HE", + "name": "Saxon-HE", + "version": "9.4", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "net.sourceforge.owlapi.owlapi-distribution", + "name": "owlapi-distribution", + "version": "5.1.18", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "com.googlecode.json-simple.json-simple", + "name": "json-simple", + "version": "1.1", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "junit.junit", + "name": "junit", + "version": "4.13.1", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "org.hamcrest.hamcrest-core", + "name": "hamcrest-core", + "version": "1.3", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.24\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file.", + "type": "Software_application" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.24\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n", + "type": "Text_excerpt", + "original_header": "Importing WIDOCO as a dependency", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file.\n", + "type": "Text_excerpt", + "original_header": "Requirements", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "package_distribution": [ + { + "result": { + "value": "jitpack.io", + "url": "https://jitpack.io", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + }, + { + "result": { + "value": "unknown-jars-temp-repo", + "name": "A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.", + "url": "file:${project.basedir}/lib", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + } + ], + "runtime_platform": [ + { + "result": { + "value": "Java: 1.8", + "version": "1.8", + "name": "Java", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + } + ], + "has_package_file": [ + { + "result": { + "value": "pom.xml", + "type": "Url" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/pom.xml" + } + ], + "readme_url": [ + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + } + ], + "contributing_guidelines": [ + { + "result": { + "value": "## Contribution guidelines\nContributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n", + "type": "File_dump" + }, + "confidence": 1, + "technique": "file_exploration", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/CONTRIBUTING.md" + } + ], + "identifier": [ + { + "result": { + "value": "https://doi.org/10.5281/zenodo.11093793", + "type": "String" + }, + "confidence": 1, + "technique": "code_parser", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/codemeta.json" + }, + { + "result": { + "type": "Url", + "value": "https://doi.org/10.5281/zenodo.11093793" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "type": "Url", + "value": "https://archive.softwareheritage.org/swh:1:rev:fec66b89a4f4acb015a44c7f8cb671d49bec626a" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "continuous_integration": [ + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/.github/workflows/ci.yml", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "ontologies": [ + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/otalex.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/ebg-ontology_edited.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/p-plan.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/bne.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/NBAMovementsv2%20-%20copia.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/System.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/retele.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/geolinkeddata.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/contaminacion-acustica.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/instrument.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/IFC4_ADD1.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/disk.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/oa.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/ssn.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/Tissue.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/wot.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/charity_org_rdf_new.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/schema_sample.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/smartProtocol.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/ontosoft-v1.0.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/IFC4_ADD1_wrongImport.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/saref4envi.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/retele-share.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/coil.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/NBAMovementsv2.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/diff/coreNew.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/diff/coilNew.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/diff/coilOld.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/diff/coreOld.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/sensor.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/observation.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/archive.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/instrument.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/inferredVariables.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/LinkedEarth/core.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/roevo.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/roterms.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/wf4ever.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/wfdesc.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/ro.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/RO/wfprov.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/benchmark/Disk/disk.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/vocabulary/1.0.0/ontology.nt", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/vocabulary/1.0.0/ontology.owl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + }, + { + "result": { + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/doc/vocabulary/1.0.0/ontology.ttl", + "type": "Url" + }, + "confidence": 1, + "technique": "file_exploration" + } + ], + "type": [ + { + "result": { + "value": "commandline-application", + "type": "String" + }, + "confidence": 0.82, + "technique": "software_type_heuristics" + } + ], + "download": [ + { + "result": { + "value": "To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest).\n", + "type": "Text_excerpt", + "original_header": "Downloading the executable", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "usage": [ + { + "result": { + "value": "Examples of the features of WIDOCO can be seen on [the gallery](https://dgarijo.github.io/Widoco/doc/gallery/)\n", + "type": "Text_excerpt", + "original_header": "Examples", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "A tutorial explaining the main features of the GUI can be found [here](https://dgarijo.github.io/Widoco/doc/tutorial/) \n", + "type": "Text_excerpt", + "original_header": "GUI Tutorial", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "To see how WIDOCO recognizes metadata annotations in your ontology to create the documentation files, see [the WIDOCO metadata documentation](doc/metadataGuide/guide.md). To learn which metadata properties we recommend adding to your ontology for producing a nice-looking documentation, have a look at our [best practices guide](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html).\n\nFor example, in order to show your logo in your documentation you just need to use `foaf:logo` as an annotation, as follows:\n```\n@prefix owl: .\n@prefix foaf: .\n a owl:Ontology ;\n foaf:logo .\n```\n\nand it will show right next to the title. The [WIDOCO metadata documentation](doc/metadataGuide/guide.md) shows all supported metadata fields.\n", + "type": "Text_excerpt", + "original_header": "Metadata usage", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "We provide JAR files for each release (see the [releases](https://github.com/dgarijo/Widoco/releases) page). However, if you want to build WIDOCO from scratch, just cd into the project folder and run:\n\n```bash\nmvn install\n```\nThe JAR will be generated in a \"JAR\" folder. The name will follow the pattern: `widoco-{VERSION_ID}-jar-with-dependencies.jar`, where {VERSION_ID} is the version number of the tool.\n", + "type": "Text_excerpt", + "original_header": "Building the JAR executable", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file.\n\nYou may also execute WIDOCO through the command line. Usage:\n```bash\njava -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS]\n```\n", + "type": "Text_excerpt", + "original_header": "JAR execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "If you don't want to use the JAR directly, you may run the project using a [Docker container](https://www.docker.com/). First you will need to download or build the image, and then run it.\n", + "type": "Text_excerpt", + "original_header": "Docker execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "We build containers in the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco) for all latest releases. In order to import one, just run the following command, stating the version of Widoco you prefer (e.g., for v1.4.23):\n\n```\ndocker pull ghcr.io/dgarijo/widoco:v1.4.23\n```\n\nTo browse all available images, see the [GitHub image registry](https://github.com/dgarijo/Widoco/pkgs/container/widoco).\n", + "type": "Text_excerpt", + "original_header": "Reusing a pre-existing image", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO", + "Docker execution" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "Build the image using the `Dockerfile` in project folder:\n\n```bash\ndocker build -t dgarijo/widoco .\n```\n", + "type": "Text_excerpt", + "original_header": "Building the image yourself", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO", + "Docker execution" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + { + "result": { + "value": "`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234\n\n`-confFile PATH`: Load your own configuration file for the ontology metadata. Use this option if you want to load your own HTML sections as well. Incompatible with -getOntologyMetadata. See [the configuration documentation](doc/configuration/configuration_doc.md) for more information about the accepted fields.\n\n`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists.\n\n`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented.\n\n`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed.\n\n`-excludeIntroduction`: Skip the introduction section in the documentation.\n\n`-excludeProvenance`: Do not add the link \"Provenance of this page\" in the metadata header section\n\n`-getOntologyMetadata`: Extract ontology metadata from the given ontology\n\n`--help`: Shows a help message and exits.\n\n`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server.\n\n\n`-ignoreIndividuals`: Individuals will not be included in the documentation.\n\n`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included)\n\n`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not.\n\n`-import`: imports a local ontology (e.g., if you don't want to load an online ontology, you may load its local version)\n\n`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by \"-\"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es\n\n`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled.\n\n`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections).\n\n`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI\n\n`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation'\n\n`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile\n\n`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/)\n\n`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution)\n\n`-rewriteBase PATH`: Change the default rewrite base path. The default value is \"/\". This flag can only be used with the htaccess option.\n\n`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology\n\n`-uniteSections`: Write all HTML sections into a single HTML document.\n\n`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila).\n\n`--version`: Shows the current version of WIDOCO.\n\n`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation.\n\n", + "type": "Text_excerpt", + "original_header": "Execution options", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "run": [ + { + "result": { + "value": "You can now execute WIDOCO through the command line. Usage:\n\n```bash\ndocker run -ti --rm dgarijo/widoco [OPTIONS]\n```\n\n**Note:** If you downloaded the image from the GitHub registry, you will have to change `dgarijo/widoco` with the name of the image you downloaded. For example `ghcr.io/dgarijo/widoco:v1.4.23`.\n\nIf you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container\nwith host directories. For instance:\n\n```bash\ndocker run -ti --rm \\\n -v `pwd`/test:/usr/local/widoco/in:Z \\\n -v `pwd`/target/generated-doc:/usr/local/widoco/out:Z \\\n dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll\n```\n", + "type": "Text_excerpt", + "original_header": "Running WIDOCO's image", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO", + "Docker execution" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "documentation": [ + { + "result": { + "value": "WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options:\n\n* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the \"load sections\" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally.\n* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers).\n\nIf you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately.\n", + "type": "Text_excerpt", + "original_header": "Browser issues (Why can't I see the generated documentation / visualization?)", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ] + }, + "confidence": 1, + "technique": "header_analysis", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "application_domain": [ + { + "result": { + "type": "String", + "value": "Semantic web" + }, + "confidence": 0.921888526958785, + "technique": "supervised_classification" + } + ], + "full_title": [ + { + "result": { + "type": "String", + "value": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "repository_status": [ + { + "result": { + "type": "Url", + "value": "https://www.repostatus.org/#active", + "description": "Active \u2013 The project has reached a stable, usable state and is being actively developed." + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ], + "logo": [ + { + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png" + }, + "confidence": 1, + "technique": "regular_expression", + "source": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/authors_files/docker_AUTHORS 2.txt b/src/somef_core/test/test_data/authors_files/docker_AUTHORS 2.txt new file mode 100644 index 0000000..3d3fe3c --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/docker_AUTHORS 2.txt @@ -0,0 +1,718 @@ +# This file lists all individuals having contributed content to the repository. +# For how it is generated, see `project/generate-authors.sh`. + +Aanand Prasad +Aaron Feng +Aaron Huslage +Abel Muiño +Abhinav Ajgaonkar +Abin Shahab +Adam Miller +Adam Singer +Aditya +Adrian Mouat +Adrien Folie +Ahmet Alp Balkan +AJ Bowen +alambike +Alan Thompson +Albert Callarisa +Albert Zhang +Aleksa Sarai +Alexander Larsson +Alexander Shopov +Alexandr Morozov +Alexey Kotlyarov +Alexey Shamrin +Alex Gaynor +Alexis THOMAS +Alex Warhawk +almoehi +Al Tobey +Álvaro Lázaro +amangoel +Amit Bakshi +AnandkumarPatel +Anand Patil +Andrea Luzzardi +Andreas Köhler +Andreas Savvides +Andreas Tiefenthaler +Andrea Turli +Andre Dublin <81dublin@gmail.com> +Andrew Duckworth +Andrew France +Andrew Macgregor +Andrew Munsell +Andrews Medina +Andrew Weiss +Andrew Williams +Andrey Petrov +Andrey Stolbovsky +Andy Chambers +andy diller +Andy Goldstein +Andy Kipp +Andy Rothfusz +Andy Smith +Andy Wilson +Anthony Bishopric +Anton Löfgren +Anton Nikitin +Antony Messerli +apocas +ArikaChen +Arnaud Porterie +Arthur Gautier +Asbjørn Enge +averagehuman +Avi Miller +Barnaby Gray +Barry Allard +Bartłomiej Piotrowski +bdevloed +Ben Firshman +Benjamin Atkin +Benoit Chesneau +Ben Sargent +Ben Toews +Ben Wiklund +Bernerd Schaefer +Bert Goethals +Bhiraj Butala +bin liu +Blake Geno +Bouke Haarsma +Boyd Hemphill +Brandon Liu +Brandon Philips +Brandon Rhodes +Brett Kochendorfer +Brian (bex) Exelbierd +Brian Dorsey +Brian Flad +Brian Goff +Brian McCallister +Brian Olsen +Brian Shumate +Brice Jaglin +Briehan Lombaard +Bruno Bigras +Bruno Binet +Bruno Renié +Bryan Bess +Bryan Matsuo +Bryan Murphy +Burke Libbey +Byung Kang +Caleb Spare +Calen Pennington +Cameron Boehmer +Carl X. Su +Charles Hooper +Charles Lindsay +Charles Merriam +Charlie Lewis +Chewey +Chia-liang Kao +Chris Alfonso +Chris Armstrong +chrismckinnel +Chris Snow +Chris St. Pierre +Christian Berendt +ChristoperBiscardi +Christopher Currie +Christopher Rigor +Christophe Troestler +Ciro S. Costa +Clayton Coleman +Colin Dunklau +Colin Rice +Colin Walters +Cory Forsyth +cressie176 +Cruceru Calin-Cristian +Daan van Berkel +Daehyeok.Mun +Dafydd Crosby +Dan Buch +Dan Cotora +Dan Griffin +Dan Hirsch +Daniel, Dao Quang Minh +Daniel Exner +Daniel Farrell +Daniel Garcia +Daniel Gasienica +Daniel Menet +Daniel Mizyrycki +Daniel Norberg +Daniel Nordberg +Daniel Robinson +Daniel Von Fange +Daniel YC Lin +Dan Keder +Dan McPherson +Danny Berger +Danny Yates +Dan Stine +Dan Walsh +Dan Williams +Darren Coxall +Darren Shepherd +David Anderson +David Calavera +David Corking +Davide Ceretti +David Gageot +David Gebler +David Mcanulty +David Pelaez +David Röthlisberger +David Sissitka +Dawn Chen +decadent +Deni Bertovic +Derek +Derek McGowan +Deric Crago +Deshi Xiao +Dinesh Subhraveti +Djibril Koné +dkumor +Dmitry Demeshchuk +Dolph Mathews +Dominik Honnef +Don Spaulding +Doug Davis +doug tangren +dragon788 +Dražen Lučanin +Dr Nic Williams +Dustin Sallings +Edmund Wagner +Eiichi Tsukata +Eike Herzbach +Eivind Uggedal +Elias Probst +Emil Hernvall +Emily Rose +Eric Hanchrow +Eric Lee +Eric Myhre +Eric Paris +Eric Windisch +Erik Hollensbe +Erik Inge Bolsø +Erik Kristensen +Erno Hopearuoho +Eugene Yakubovich +eugenkrizo +evanderkoogh +Evan Hazlett +Evan Krall +Evan Phoenix +Evan Wies +Eystein Måløy Stenberg +ezbercih +Fabio Falci +Fabio Rehm +Fabrizio Regini +Faiz Khan +Fareed Dudhia +Felix Rabe +Fernando +Filipe Brandenburger +Flavio Castelli +FLGMwt +Francisco Carriedo +Francisco Souza +Frank Macreery +Frank Rosquin +Frederick F. Kautz IV +Frederik Loeffert +Fred Lifton +Freek Kalter +Gabe Rosenhouse +Gabor Nagy +Gabriel Monroy +Galen Sampson +Gareth Rushgrove +gautam, prasanna +Geoffrey Bachelet +George Xie +Gereon Frey +German DZ +Gert van Valkenhoef +Giuseppe Mazzotta +Gleb Fotengauer-Malinovskiy +Gleb M Borisov +Glyn Normington +Goffert van Gool +golubbe +Graydon Hoare +Greg Thornton +grunny +Guilherme Salgado +Guillaume Dufour +Guillaume J. Charmes +Gurjeet Singh +Guruprasad +Hans Rødtang +Harald Albers +Harley Laue +Hector Castro +Henning Sprang +Hobofan +Hollie Teal +Huayi Zhang +Hugo Duncan +Hunter Blanks +Hu Tao +Huu Nguyen +hyeongkyu.lee +Ian Babrou +Ian Bull +Ian Main +Ian Truslove +Igor Dolzhikov +ILYA Khlopotov +inglesp +Isaac Dupree +Isabel Jimenez +Isao Jonas +Ivan Fraixedes +Jack Danger Canty +jakedt +Jake Moshenko +James Allen +James Carr +James DeFelice +James Harrison Fisher +James Kyle +James Mills +James Turnbull +Jan Keromnes +Jan Pazdziora +Jan Toebes +Jaroslaw Zabiello +jaseg +Jason Giedymin +Jason Hall +Jason Livesay +Jason McVetta +Jason Plum +Jean-Baptiste Barth +Jean-Baptiste Dalido +Jean-Paul Calderone +Jeff Lindsay +Jeffrey Bolle +Jeff Welch +Jeremy Grosser +Jérôme Petazzoni +Jesse Dubay +Jessica Frazelle +Jezeniel Zapanta +Jilles Oldenbeuving +Jim Alateras +Jimmy Cuadra +Jim Perrin +Jiří Župka +Joe Beda +Joe Ferguson +Joel Handwell +Joe Shaw +Joe Van Dyk +Joffrey F +Johan Euphrosine +Johannes 'fish' Ziemke +Johan Rydberg +John Costa +John Feminella +John Gardiner Myers +John Gossman +John OBrien III +John Warwick +Jonas Pfenniger +Jonathan Boulle +Jonathan Camp +Jonathan McCrohan +Jonathan Mueller +Jonathan Pares +Jonathan Rudenberg +Jon Wedaman +Joost Cassee +Jordan Arentsen +Jordan Sissel +Joseph Anthony Pasquale Holsten +Joseph Hager +Josh Hawn +Josh +Josh Poimboeuf +Josiah Kiehl +JP +Julian Taylor +Julien Barbier +Julien Bordellier +Julien Dubois +Justin Force +Justin Plock +Justin Simonelis +Jyrki Puttonen +Karan Lyons +Karl Grzeszczak +Kato Kazuyoshi +Kawsar Saiyeed +Keli Hu +Ken Cochrane +Ken ICHIKAWA +Kevin Clark +Kevin J. Lynagh +Kevin Menard +Kevin "qwazerty" Houdebert +Kevin Wallace +Keyvan Fatehi +kies +kim0 +Kim BKC Carlbacker +Kimbro Staken +Kiran Gangadharan +knappe +Kohei Tsuruta +Konrad Kleine +Konstantin Pelykh +krrg +Kyle Conroy +kyu +Lachlan Coote +Lajos Papp +Lakshan Perera +lalyos +Lance Chen +Lars R. Damerow +Laurie Voss +leeplay +Lei Jitang +Len Weincier +Leszek Kowalski +Levi Gross +Lewis Peckover +Liang-Chi Hsieh +limsy +Lokesh Mandvekar +Louis Opter +lukaspustina +lukemarsden +Madhu Venugopal +Mahesh Tiyyagura +Malte Janduda +Manfred Zabarauskas +Manuel Meurer +Manuel Woelker +Marc Abramowitz +Marc Kuo +Marco Hennings +Marc Tamsky +Marcus Farkas +marcuslinke +Marcus Ramberg +Marek Goldmann +Marius Voila +Mark Allen +Mark McGranaghan +Marko Mikulicic +Marko Tibold +Markus Fix +Martijn van Oosterhout +Martin Redmond +Mason Malone +Mateusz Sulima +Mathias Monnerville +Mathieu Le Marec - Pasquet +Matt Apperson +Matt Bachmann +Matt Haggard +Matthew Heon +Matthew Mueller +Matthias Klumpp +Matthias Kühnle +mattymo +mattyw +Maxime Petazzoni +Maxim Treskin +Max Shytikov +Médi-Rémi Hashim +meejah +Mengdi Gao +Mert Yazıcıoğlu +Michael Brown +Michael Crosby +Michael Gorsuch +Michael Hudson-Doyle +Michael Neale +Michaël Pailloncy +Michael Prokop +Michael Scharf +Michael Stapelberg +Michael Thies +Michal Jemala +Michiel@unhosted +Miguel Angel Fernández +Mike Chelen +Mike Gaffney +Mike MacCana +Mike Naberezny +Mike Snitzer +Mikhail Sobolev +Mohit Soni +Morgante Pell +Morten Siebuhr +Mrunal Patel +mschurenko +Mustafa Akın +Nan Monnand Deng +Naoki Orii +Nate Jones +Nathan Hsieh +Nathan Kleyn +Nathan LeClaire +Nelson Chen +Niall O'Higgins +Nicholas E. Rabenau +Nick Payne +Nick Stenning +Nick Stinemates +Nicolas De loof +Nicolas Dudebout +Nicolas Goy +Nicolas Kaiser +NikolaMandic +noducks +Nolan Darilek +nzwsch +OddBloke +odk- +Oguz Bilgic +Oh Jinkyun +Ole Reifschneider +Olivier Gambier +O.S. Tezer +pandrew +Pascal Borreli +Pascal Hartig +Patrick Hemmer +pattichen +Paul Annesley +Paul Bowsher +Paul Hammond +Paul Jimenez +Paul Lietar +Paul Morie +Paul Nasrat +Paul +Paul Weaver +Pavlos Ratis +Peter Bourgon +Peter Braden +Peter Ericson +Peter Salvatore +Peter Waller +Phil Estes +Philipp Weissensteiner +Phillip Alexander +Phil Spitler +Phil +Piergiuliano Bossi +Pierre-Alain RIVIERE +Pierre +Piotr Bogdan +pixelistik +Prasanna Gautam +Przemek Hejman +pysqz +Qiang Huang +Quentin Brossard +r0n22 +Rafal Jeczalik +Rafe Colton +Rajat Pandit +Rajdeep Dua +Ralph Bean +Ramkumar Ramachandra +Ramon van Alteren +Recursive Madman +Remi Rampin +Renato Riccieri Santos Zannon +rgstephens +Rhys Hiltner +Richard Harvey +Richo Healey +Rick Bradley +Rick van de Loo +Robert Bachmann +Robert Bittle +Robert Obryk +Roberto G. Hashioka +Robin Speekenbrink +robpc +Rodrigo Vaz +Roel Van Nyen +Roger Peppe +Rohit Jnagal +Roland Huß +Roland Moriz +Ron Smits +Rovanion Luckey +Rudolph Gottesheim +Ryan Anderson +Ryan Aslett +Ryan Detzel +Ryan Fowler +Ryan O'Donnell +Ryan Seto +Ryan Thomas +Sam Alba +Sam Bailey +Sam J Sharpe +Sam Reis +Sam Rijs +Samuel Andaya +Samuel PHAN +satoru +Satoshi Amemiya +Scott Bessler +Scott Collier +Scott Johnston +Scott Walls +Sean Cronin +Sean P. Kane +Sebastiaan van Stijn +Sébastien Luttringer +Sébastien +Sébastien Stormacq +Senthil Kumar Selvaraj +SeongJae Park +Shane Canon +shaunol +Shawn Landden +Shawn Siefkas +Shih-Yuan Lee +shuai-z +Silas Sewell +Simon Taranto +Sindhu S +Sjoerd Langkemper +s-ko +Solomon Hykes +Song Gao +Soulou +soulshake +Sridatta Thatipamala +Sridhar Ratnakumar +Srini Brahmaroutu +Steeve Morin +Stefan Praszalowicz +Stephen Crosby +Steven Burgess +Steven Merrill +sudosurootdev +Sven Dowideit +Sylvain Bellemare +tang0th +Tatsuki Sugiura +Ted M. Young +Tehmasp Chaudhri +Thatcher Peskens +Thermionix +Thijs Terlouw +Thomas Bikeev +Thomas Frössman +Thomas Hansen +Thomas LEVEIL +Thomas Orozco +Thomas Schroeter +Tianon Gravi +Tibor Vass +Tim Bosse +Tim Hockin +Timothy Hobbs +Tim Ruffles +Tim Smith +Tim Terhorst +tjmehta +tjwebb123 +tobe +Tobias Bieniek +Tobias Gesellchen +Tobias Schmidt +Tobias Schwab +Todd Lunter +Tomasz Lipinski +Tom Fotherby +Tom Hulihan +Tom Maaswinkel +Tommaso Visconti +Tonis Tiigi +Tony Daws +Torstein Husebø +tpng +Travis Cline +Trent Ogren +Tyler Brock +Tzu-Jung Lee +Ulysse Carion +unclejack +vgeta +Victor Coisne +Victor Lyuboslavsky +Victor Marmol +Victor Vieux +Viktor Vojnovski +Vincent Batts +Vincent Bernat +Vincent Bernat +Vincent Giersch +Vincent Mayers +Vincent Woo +Vinod Kulkarni +Vishal Doshi +Vishnu Kannan +Vitor Monteiro +Vivek Agarwal +Vivek Dasgupta +Vivek Goyal +Vladimir Bulyga +Vladimir Kirillov +Vladimir Rutsky +Vojtech Vitek (V-Teq) +waitingkuo +Walter Leibbrandt +Walter Stanish +Ward Vandewege +WarheadsSE +Wes Morgan +Will Dietz +William Delanoue +William Henry +William Riancho +William Thurston +Will Rouesnel +Will Weaver +wyc +Xiuming Chen +xuzhaokui +Yang Bai +Yasunori Mahata +Yohei Ueda +Yurii Rashkovskii +Zac Dover +Zach Borboa +Zain Memon +Zaiste! +Zane DeGraffenried +Zilin Du +zimbatm +Zoltan Tombol +zqh +尹吉峰 diff --git a/src/somef_core/test/test_data/authors_files/docker_AUTHORS.txt b/src/somef_core/test/test_data/authors_files/docker_AUTHORS.txt new file mode 100644 index 0000000..3d3fe3c --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/docker_AUTHORS.txt @@ -0,0 +1,718 @@ +# This file lists all individuals having contributed content to the repository. +# For how it is generated, see `project/generate-authors.sh`. + +Aanand Prasad +Aaron Feng +Aaron Huslage +Abel Muiño +Abhinav Ajgaonkar +Abin Shahab +Adam Miller +Adam Singer +Aditya +Adrian Mouat +Adrien Folie +Ahmet Alp Balkan +AJ Bowen +alambike +Alan Thompson +Albert Callarisa +Albert Zhang +Aleksa Sarai +Alexander Larsson +Alexander Shopov +Alexandr Morozov +Alexey Kotlyarov +Alexey Shamrin +Alex Gaynor +Alexis THOMAS +Alex Warhawk +almoehi +Al Tobey +Álvaro Lázaro +amangoel +Amit Bakshi +AnandkumarPatel +Anand Patil +Andrea Luzzardi +Andreas Köhler +Andreas Savvides +Andreas Tiefenthaler +Andrea Turli +Andre Dublin <81dublin@gmail.com> +Andrew Duckworth +Andrew France +Andrew Macgregor +Andrew Munsell +Andrews Medina +Andrew Weiss +Andrew Williams +Andrey Petrov +Andrey Stolbovsky +Andy Chambers +andy diller +Andy Goldstein +Andy Kipp +Andy Rothfusz +Andy Smith +Andy Wilson +Anthony Bishopric +Anton Löfgren +Anton Nikitin +Antony Messerli +apocas +ArikaChen +Arnaud Porterie +Arthur Gautier +Asbjørn Enge +averagehuman +Avi Miller +Barnaby Gray +Barry Allard +Bartłomiej Piotrowski +bdevloed +Ben Firshman +Benjamin Atkin +Benoit Chesneau +Ben Sargent +Ben Toews +Ben Wiklund +Bernerd Schaefer +Bert Goethals +Bhiraj Butala +bin liu +Blake Geno +Bouke Haarsma +Boyd Hemphill +Brandon Liu +Brandon Philips +Brandon Rhodes +Brett Kochendorfer +Brian (bex) Exelbierd +Brian Dorsey +Brian Flad +Brian Goff +Brian McCallister +Brian Olsen +Brian Shumate +Brice Jaglin +Briehan Lombaard +Bruno Bigras +Bruno Binet +Bruno Renié +Bryan Bess +Bryan Matsuo +Bryan Murphy +Burke Libbey +Byung Kang +Caleb Spare +Calen Pennington +Cameron Boehmer +Carl X. Su +Charles Hooper +Charles Lindsay +Charles Merriam +Charlie Lewis +Chewey +Chia-liang Kao +Chris Alfonso +Chris Armstrong +chrismckinnel +Chris Snow +Chris St. Pierre +Christian Berendt +ChristoperBiscardi +Christopher Currie +Christopher Rigor +Christophe Troestler +Ciro S. Costa +Clayton Coleman +Colin Dunklau +Colin Rice +Colin Walters +Cory Forsyth +cressie176 +Cruceru Calin-Cristian +Daan van Berkel +Daehyeok.Mun +Dafydd Crosby +Dan Buch +Dan Cotora +Dan Griffin +Dan Hirsch +Daniel, Dao Quang Minh +Daniel Exner +Daniel Farrell +Daniel Garcia +Daniel Gasienica +Daniel Menet +Daniel Mizyrycki +Daniel Norberg +Daniel Nordberg +Daniel Robinson +Daniel Von Fange +Daniel YC Lin +Dan Keder +Dan McPherson +Danny Berger +Danny Yates +Dan Stine +Dan Walsh +Dan Williams +Darren Coxall +Darren Shepherd +David Anderson +David Calavera +David Corking +Davide Ceretti +David Gageot +David Gebler +David Mcanulty +David Pelaez +David Röthlisberger +David Sissitka +Dawn Chen +decadent +Deni Bertovic +Derek +Derek McGowan +Deric Crago +Deshi Xiao +Dinesh Subhraveti +Djibril Koné +dkumor +Dmitry Demeshchuk +Dolph Mathews +Dominik Honnef +Don Spaulding +Doug Davis +doug tangren +dragon788 +Dražen Lučanin +Dr Nic Williams +Dustin Sallings +Edmund Wagner +Eiichi Tsukata +Eike Herzbach +Eivind Uggedal +Elias Probst +Emil Hernvall +Emily Rose +Eric Hanchrow +Eric Lee +Eric Myhre +Eric Paris +Eric Windisch +Erik Hollensbe +Erik Inge Bolsø +Erik Kristensen +Erno Hopearuoho +Eugene Yakubovich +eugenkrizo +evanderkoogh +Evan Hazlett +Evan Krall +Evan Phoenix +Evan Wies +Eystein Måløy Stenberg +ezbercih +Fabio Falci +Fabio Rehm +Fabrizio Regini +Faiz Khan +Fareed Dudhia +Felix Rabe +Fernando +Filipe Brandenburger +Flavio Castelli +FLGMwt +Francisco Carriedo +Francisco Souza +Frank Macreery +Frank Rosquin +Frederick F. Kautz IV +Frederik Loeffert +Fred Lifton +Freek Kalter +Gabe Rosenhouse +Gabor Nagy +Gabriel Monroy +Galen Sampson +Gareth Rushgrove +gautam, prasanna +Geoffrey Bachelet +George Xie +Gereon Frey +German DZ +Gert van Valkenhoef +Giuseppe Mazzotta +Gleb Fotengauer-Malinovskiy +Gleb M Borisov +Glyn Normington +Goffert van Gool +golubbe +Graydon Hoare +Greg Thornton +grunny +Guilherme Salgado +Guillaume Dufour +Guillaume J. Charmes +Gurjeet Singh +Guruprasad +Hans Rødtang +Harald Albers +Harley Laue +Hector Castro +Henning Sprang +Hobofan +Hollie Teal +Huayi Zhang +Hugo Duncan +Hunter Blanks +Hu Tao +Huu Nguyen +hyeongkyu.lee +Ian Babrou +Ian Bull +Ian Main +Ian Truslove +Igor Dolzhikov +ILYA Khlopotov +inglesp +Isaac Dupree +Isabel Jimenez +Isao Jonas +Ivan Fraixedes +Jack Danger Canty +jakedt +Jake Moshenko +James Allen +James Carr +James DeFelice +James Harrison Fisher +James Kyle +James Mills +James Turnbull +Jan Keromnes +Jan Pazdziora +Jan Toebes +Jaroslaw Zabiello +jaseg +Jason Giedymin +Jason Hall +Jason Livesay +Jason McVetta +Jason Plum +Jean-Baptiste Barth +Jean-Baptiste Dalido +Jean-Paul Calderone +Jeff Lindsay +Jeffrey Bolle +Jeff Welch +Jeremy Grosser +Jérôme Petazzoni +Jesse Dubay +Jessica Frazelle +Jezeniel Zapanta +Jilles Oldenbeuving +Jim Alateras +Jimmy Cuadra +Jim Perrin +Jiří Župka +Joe Beda +Joe Ferguson +Joel Handwell +Joe Shaw +Joe Van Dyk +Joffrey F +Johan Euphrosine +Johannes 'fish' Ziemke +Johan Rydberg +John Costa +John Feminella +John Gardiner Myers +John Gossman +John OBrien III +John Warwick +Jonas Pfenniger +Jonathan Boulle +Jonathan Camp +Jonathan McCrohan +Jonathan Mueller +Jonathan Pares +Jonathan Rudenberg +Jon Wedaman +Joost Cassee +Jordan Arentsen +Jordan Sissel +Joseph Anthony Pasquale Holsten +Joseph Hager +Josh Hawn +Josh +Josh Poimboeuf +Josiah Kiehl +JP +Julian Taylor +Julien Barbier +Julien Bordellier +Julien Dubois +Justin Force +Justin Plock +Justin Simonelis +Jyrki Puttonen +Karan Lyons +Karl Grzeszczak +Kato Kazuyoshi +Kawsar Saiyeed +Keli Hu +Ken Cochrane +Ken ICHIKAWA +Kevin Clark +Kevin J. Lynagh +Kevin Menard +Kevin "qwazerty" Houdebert +Kevin Wallace +Keyvan Fatehi +kies +kim0 +Kim BKC Carlbacker +Kimbro Staken +Kiran Gangadharan +knappe +Kohei Tsuruta +Konrad Kleine +Konstantin Pelykh +krrg +Kyle Conroy +kyu +Lachlan Coote +Lajos Papp +Lakshan Perera +lalyos +Lance Chen +Lars R. Damerow +Laurie Voss +leeplay +Lei Jitang +Len Weincier +Leszek Kowalski +Levi Gross +Lewis Peckover +Liang-Chi Hsieh +limsy +Lokesh Mandvekar +Louis Opter +lukaspustina +lukemarsden +Madhu Venugopal +Mahesh Tiyyagura +Malte Janduda +Manfred Zabarauskas +Manuel Meurer +Manuel Woelker +Marc Abramowitz +Marc Kuo +Marco Hennings +Marc Tamsky +Marcus Farkas +marcuslinke +Marcus Ramberg +Marek Goldmann +Marius Voila +Mark Allen +Mark McGranaghan +Marko Mikulicic +Marko Tibold +Markus Fix +Martijn van Oosterhout +Martin Redmond +Mason Malone +Mateusz Sulima +Mathias Monnerville +Mathieu Le Marec - Pasquet +Matt Apperson +Matt Bachmann +Matt Haggard +Matthew Heon +Matthew Mueller +Matthias Klumpp +Matthias Kühnle +mattymo +mattyw +Maxime Petazzoni +Maxim Treskin +Max Shytikov +Médi-Rémi Hashim +meejah +Mengdi Gao +Mert Yazıcıoğlu +Michael Brown +Michael Crosby +Michael Gorsuch +Michael Hudson-Doyle +Michael Neale +Michaël Pailloncy +Michael Prokop +Michael Scharf +Michael Stapelberg +Michael Thies +Michal Jemala +Michiel@unhosted +Miguel Angel Fernández +Mike Chelen +Mike Gaffney +Mike MacCana +Mike Naberezny +Mike Snitzer +Mikhail Sobolev +Mohit Soni +Morgante Pell +Morten Siebuhr +Mrunal Patel +mschurenko +Mustafa Akın +Nan Monnand Deng +Naoki Orii +Nate Jones +Nathan Hsieh +Nathan Kleyn +Nathan LeClaire +Nelson Chen +Niall O'Higgins +Nicholas E. Rabenau +Nick Payne +Nick Stenning +Nick Stinemates +Nicolas De loof +Nicolas Dudebout +Nicolas Goy +Nicolas Kaiser +NikolaMandic +noducks +Nolan Darilek +nzwsch +OddBloke +odk- +Oguz Bilgic +Oh Jinkyun +Ole Reifschneider +Olivier Gambier +O.S. Tezer +pandrew +Pascal Borreli +Pascal Hartig +Patrick Hemmer +pattichen +Paul Annesley +Paul Bowsher +Paul Hammond +Paul Jimenez +Paul Lietar +Paul Morie +Paul Nasrat +Paul +Paul Weaver +Pavlos Ratis +Peter Bourgon +Peter Braden +Peter Ericson +Peter Salvatore +Peter Waller +Phil Estes +Philipp Weissensteiner +Phillip Alexander +Phil Spitler +Phil +Piergiuliano Bossi +Pierre-Alain RIVIERE +Pierre +Piotr Bogdan +pixelistik +Prasanna Gautam +Przemek Hejman +pysqz +Qiang Huang +Quentin Brossard +r0n22 +Rafal Jeczalik +Rafe Colton +Rajat Pandit +Rajdeep Dua +Ralph Bean +Ramkumar Ramachandra +Ramon van Alteren +Recursive Madman +Remi Rampin +Renato Riccieri Santos Zannon +rgstephens +Rhys Hiltner +Richard Harvey +Richo Healey +Rick Bradley +Rick van de Loo +Robert Bachmann +Robert Bittle +Robert Obryk +Roberto G. Hashioka +Robin Speekenbrink +robpc +Rodrigo Vaz +Roel Van Nyen +Roger Peppe +Rohit Jnagal +Roland Huß +Roland Moriz +Ron Smits +Rovanion Luckey +Rudolph Gottesheim +Ryan Anderson +Ryan Aslett +Ryan Detzel +Ryan Fowler +Ryan O'Donnell +Ryan Seto +Ryan Thomas +Sam Alba +Sam Bailey +Sam J Sharpe +Sam Reis +Sam Rijs +Samuel Andaya +Samuel PHAN +satoru +Satoshi Amemiya +Scott Bessler +Scott Collier +Scott Johnston +Scott Walls +Sean Cronin +Sean P. Kane +Sebastiaan van Stijn +Sébastien Luttringer +Sébastien +Sébastien Stormacq +Senthil Kumar Selvaraj +SeongJae Park +Shane Canon +shaunol +Shawn Landden +Shawn Siefkas +Shih-Yuan Lee +shuai-z +Silas Sewell +Simon Taranto +Sindhu S +Sjoerd Langkemper +s-ko +Solomon Hykes +Song Gao +Soulou +soulshake +Sridatta Thatipamala +Sridhar Ratnakumar +Srini Brahmaroutu +Steeve Morin +Stefan Praszalowicz +Stephen Crosby +Steven Burgess +Steven Merrill +sudosurootdev +Sven Dowideit +Sylvain Bellemare +tang0th +Tatsuki Sugiura +Ted M. Young +Tehmasp Chaudhri +Thatcher Peskens +Thermionix +Thijs Terlouw +Thomas Bikeev +Thomas Frössman +Thomas Hansen +Thomas LEVEIL +Thomas Orozco +Thomas Schroeter +Tianon Gravi +Tibor Vass +Tim Bosse +Tim Hockin +Timothy Hobbs +Tim Ruffles +Tim Smith +Tim Terhorst +tjmehta +tjwebb123 +tobe +Tobias Bieniek +Tobias Gesellchen +Tobias Schmidt +Tobias Schwab +Todd Lunter +Tomasz Lipinski +Tom Fotherby +Tom Hulihan +Tom Maaswinkel +Tommaso Visconti +Tonis Tiigi +Tony Daws +Torstein Husebø +tpng +Travis Cline +Trent Ogren +Tyler Brock +Tzu-Jung Lee +Ulysse Carion +unclejack +vgeta +Victor Coisne +Victor Lyuboslavsky +Victor Marmol +Victor Vieux +Viktor Vojnovski +Vincent Batts +Vincent Bernat +Vincent Bernat +Vincent Giersch +Vincent Mayers +Vincent Woo +Vinod Kulkarni +Vishal Doshi +Vishnu Kannan +Vitor Monteiro +Vivek Agarwal +Vivek Dasgupta +Vivek Goyal +Vladimir Bulyga +Vladimir Kirillov +Vladimir Rutsky +Vojtech Vitek (V-Teq) +waitingkuo +Walter Leibbrandt +Walter Stanish +Ward Vandewege +WarheadsSE +Wes Morgan +Will Dietz +William Delanoue +William Henry +William Riancho +William Thurston +Will Rouesnel +Will Weaver +wyc +Xiuming Chen +xuzhaokui +Yang Bai +Yasunori Mahata +Yohei Ueda +Yurii Rashkovskii +Zac Dover +Zach Borboa +Zain Memon +Zaiste! +Zane DeGraffenried +Zilin Du +zimbatm +Zoltan Tombol +zqh +尹吉峰 diff --git a/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS 2.txt b/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS 2.txt new file mode 100644 index 0000000..1234b78 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS 2.txt @@ -0,0 +1,13 @@ +# This is the list of IREE's significant contributors. +# +# This does not necessarily list everyone who has contributed code, especially +# since many employees of one corporation may be contributing. To see the full +# list of contributors, see the revision history in source control. +# +# Please only add individuals if they are not contributing on behalf of a +# company (who should be listed instead). Add new entries at the bottom of the +# file. +Google LLC +Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. for its Fraunhofer Institute for Material Flow and Logistics (IML) +Nod, Inc. +Advanced Micro Devices, Inc. diff --git a/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS.txt b/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS.txt new file mode 100644 index 0000000..1234b78 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/ireeOrg_AUTHORS.txt @@ -0,0 +1,13 @@ +# This is the list of IREE's significant contributors. +# +# This does not necessarily list everyone who has contributed code, especially +# since many employees of one corporation may be contributing. To see the full +# list of contributors, see the revision history in source control. +# +# Please only add individuals if they are not contributing on behalf of a +# company (who should be listed instead). Add new entries at the bottom of the +# file. +Google LLC +Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. for its Fraunhofer Institute for Material Flow and Logistics (IML) +Nod, Inc. +Advanced Micro Devices, Inc. diff --git a/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS 2.txt b/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS 2.txt new file mode 100644 index 0000000..8814941 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS 2.txt @@ -0,0 +1,10 @@ +# This is the official list of project authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS.txt file. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization + +JetBrains <> +Philipp Nurullin +Konstantin Bulenkov diff --git a/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS.txt b/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS.txt new file mode 100644 index 0000000..8814941 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/jetBrain_AUTHORS.txt @@ -0,0 +1,10 @@ +# This is the official list of project authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS.txt file. +# See the latter for an explanation. +# +# Names should be added to this file as: +# Name or Organization + +JetBrains <> +Philipp Nurullin +Konstantin Bulenkov diff --git a/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS 2.txt b/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS 2.txt new file mode 100644 index 0000000..a8ec52d --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS 2.txt @@ -0,0 +1,9 @@ + +********************************************************************** + +***************************Main dev team****************************** + + +- Julien Dombre (moyo at indepnet.org) + +********************************************************************** diff --git a/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS.txt b/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS.txt new file mode 100644 index 0000000..a8ec52d --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/pluginsGLPI_AUTHORS.txt @@ -0,0 +1,9 @@ + +********************************************************************** + +***************************Main dev team****************************** + + +- Julien Dombre (moyo at indepnet.org) + +********************************************************************** diff --git a/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS 2.txt b/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS 2.txt new file mode 100644 index 0000000..434a7a4 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS 2.txt @@ -0,0 +1,11 @@ +# This is the official list of TensorFlow authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. + +Google Inc. +Yuan Tang +Arm Ltd diff --git a/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS.txt b/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS.txt new file mode 100644 index 0000000..434a7a4 --- /dev/null +++ b/src/somef_core/test/test_data/authors_files/tensorFlow_AUTHORS.txt @@ -0,0 +1,11 @@ +# This is the official list of TensorFlow authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as: +# Name or Organization +# The email address is not required for organizations. + +Google Inc. +Yuan Tang +Arm Ltd diff --git a/src/somef_core/test/test_data/expected/Widoco 2.yaml b/src/somef_core/test/test_data/expected/Widoco 2.yaml new file mode 100644 index 0000000..a7465b3 --- /dev/null +++ b/src/somef_core/test/test_data/expected/Widoco 2.yaml @@ -0,0 +1,29 @@ +CAT_NAME: Widoco # Passed +CAT_CODE_REPOSITORY: https://github.com/dgarijo/Widoco # Passed +CAT_ISSUE_TRACKER: https://github.com/dgarijo/Widoco/issues # Passed +CAT_DATE_CREATED: "2013-07-15" # Passed +CAT_DATE_UPDATED: "2025-01-31" # Passed +CAT_DOWNLOAD_URL: https://github.com/dgarijo/Widoco/releases # Passed +CAT_README_URL: # Passed + value: "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + +CAT_KEYWORDS: # Passed + - documentation + - metadata + - ontology + - ontology-diagram + - ontology-evaluation + - wizard +CAT_LICENSE: # Passed + value: Apache License 2.0 +CAT_VERSION: v1.4.25 # Passed +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.11093793 # Passed +CAT_DESCRIPTION: # Passed + - "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template." + - "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" # Passed +CAT_CITATION: # Passed + title: "WIDOCO: a wizard for documenting ontologies" + type: Scholarly_article + url: http://dgarijo.com/papers/widoco-iswc2017.pdf + date_published: "2017" + doi: "10.1007/978-3-319-68204-4_9" diff --git a/src/somef_core/test/test_data/expected/Widoco.yaml b/src/somef_core/test/test_data/expected/Widoco.yaml new file mode 100644 index 0000000..a7465b3 --- /dev/null +++ b/src/somef_core/test/test_data/expected/Widoco.yaml @@ -0,0 +1,29 @@ +CAT_NAME: Widoco # Passed +CAT_CODE_REPOSITORY: https://github.com/dgarijo/Widoco # Passed +CAT_ISSUE_TRACKER: https://github.com/dgarijo/Widoco/issues # Passed +CAT_DATE_CREATED: "2013-07-15" # Passed +CAT_DATE_UPDATED: "2025-01-31" # Passed +CAT_DOWNLOAD_URL: https://github.com/dgarijo/Widoco/releases # Passed +CAT_README_URL: # Passed + value: "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + +CAT_KEYWORDS: # Passed + - documentation + - metadata + - ontology + - ontology-diagram + - ontology-evaluation + - wizard +CAT_LICENSE: # Passed + value: Apache License 2.0 +CAT_VERSION: v1.4.25 # Passed +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.11093793 # Passed +CAT_DESCRIPTION: # Passed + - "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template." + - "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" # Passed +CAT_CITATION: # Passed + title: "WIDOCO: a wizard for documenting ontologies" + type: Scholarly_article + url: http://dgarijo.com/papers/widoco-iswc2017.pdf + date_published: "2017" + doi: "10.1007/978-3-319-68204-4_9" diff --git a/src/somef_core/test/test_data/expected/aladin-lite 2.yaml b/src/somef_core/test/test_data/expected/aladin-lite 2.yaml new file mode 100644 index 0000000..2c4b654 --- /dev/null +++ b/src/somef_core/test/test_data/expected/aladin-lite 2.yaml @@ -0,0 +1,22 @@ +CAT_NAME: Aladin Lite # Passed +CAT_CODE_REPOSITORY: https://github.com/cds-astro/aladin-lite # Passed +CAT_ISSUE_TRACKER: https://github.com/cds-astro/aladin-lite/issues # Passed +CAT_DATE_CREATED: "2013-05-01" # Passed +CAT_DATE_UPDATED: "2023-01-31" # Passed +CAT_DATE_PUBLISHED: "2013-05-01" # Passed +CAT_README_URL: # Passed + value: "https://aladin.cds.unistra.fr/AladinLite/doc/" +CAT_KEYWORDS: # Passed + - IVOA + - Astronomy +CAT_LICENSE: https://spdx.org/licenses/GPL-3.0 # Passed +CAT_VERSION: 3.6.1 # Passed +CAT_IDENTIFIER: 10.5281/zenodo.7638833 # Passed +CAT_DESCRIPTION: An astronomical HiPS visualizer in the browser. # Passed +CAT_AUTHORS: # Passed + value: Matthieu Baumann + type: String + email: matthieu.baumann@unistra.fr + affiliation: "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + identifier: "https://orcid.org/0000-0002-7123-773X" +CAT_CITATION: http://aspbooks.org/publications/532/007.pdf # Passed diff --git a/src/somef_core/test/test_data/expected/aladin-lite.yaml b/src/somef_core/test/test_data/expected/aladin-lite.yaml new file mode 100644 index 0000000..2c4b654 --- /dev/null +++ b/src/somef_core/test/test_data/expected/aladin-lite.yaml @@ -0,0 +1,22 @@ +CAT_NAME: Aladin Lite # Passed +CAT_CODE_REPOSITORY: https://github.com/cds-astro/aladin-lite # Passed +CAT_ISSUE_TRACKER: https://github.com/cds-astro/aladin-lite/issues # Passed +CAT_DATE_CREATED: "2013-05-01" # Passed +CAT_DATE_UPDATED: "2023-01-31" # Passed +CAT_DATE_PUBLISHED: "2013-05-01" # Passed +CAT_README_URL: # Passed + value: "https://aladin.cds.unistra.fr/AladinLite/doc/" +CAT_KEYWORDS: # Passed + - IVOA + - Astronomy +CAT_LICENSE: https://spdx.org/licenses/GPL-3.0 # Passed +CAT_VERSION: 3.6.1 # Passed +CAT_IDENTIFIER: 10.5281/zenodo.7638833 # Passed +CAT_DESCRIPTION: An astronomical HiPS visualizer in the browser. # Passed +CAT_AUTHORS: # Passed + value: Matthieu Baumann + type: String + email: matthieu.baumann@unistra.fr + affiliation: "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + identifier: "https://orcid.org/0000-0002-7123-773X" +CAT_CITATION: http://aspbooks.org/publications/532/007.pdf # Passed diff --git a/src/somef_core/test/test_data/expected/gammapy 2.yaml b/src/somef_core/test/test_data/expected/gammapy 2.yaml new file mode 100644 index 0000000..4d89b73 --- /dev/null +++ b/src/somef_core/test/test_data/expected/gammapy 2.yaml @@ -0,0 +1,31 @@ +CAT_NAME: "Gammapy: Python toolbox for gamma-ray astronomy" # Passed +CAT_CODE_REPOSITORY: https://github.com/gammapy/gammapy # Passed +CAT_ISSUE_TRACKER: https://github.com/gammapy/gammapy/issues # Passed +CAT_DATE_UPDATED: "2024-11-29" # Passed +CAT_DATE_PUBLISHED: "2024-11-26" # Passed +CAT_README_URL: # Passed + value: "https://gammapy.org" + +CAT_KEYWORDS: # Passed + - Astronomy + - Gamma-rays + - Data analysis + +CAT_LICENSE: # Passed + value: https://spdx.org/licenses/BSD-3-Clause + +CAT_VERSION: v1.3 # Passed + +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.4701488 # Passed + +CAT_DESCRIPTION: Gammapy analyzes gamma-ray data and creates sky images, spectra and lightcurves, from event lists and instrument response information; it can also determine the position, morphology and spectra of gamma-ray sources. It is used to analyze data from H.E.S.S., Fermi-LAT, HAWC, and the Cherenkov Telescope Array (CTA). # Passed + +CAT_REQUIREMENTS: # Passed + value: numpy>=1.21 + name: numpy + version: ">=1.21" + type: Software_application + +CAT_AUTHORS: # Passed + value: Fabio Acero + type: String \ No newline at end of file diff --git a/src/somef_core/test/test_data/expected/gammapy.yaml b/src/somef_core/test/test_data/expected/gammapy.yaml new file mode 100644 index 0000000..4d89b73 --- /dev/null +++ b/src/somef_core/test/test_data/expected/gammapy.yaml @@ -0,0 +1,31 @@ +CAT_NAME: "Gammapy: Python toolbox for gamma-ray astronomy" # Passed +CAT_CODE_REPOSITORY: https://github.com/gammapy/gammapy # Passed +CAT_ISSUE_TRACKER: https://github.com/gammapy/gammapy/issues # Passed +CAT_DATE_UPDATED: "2024-11-29" # Passed +CAT_DATE_PUBLISHED: "2024-11-26" # Passed +CAT_README_URL: # Passed + value: "https://gammapy.org" + +CAT_KEYWORDS: # Passed + - Astronomy + - Gamma-rays + - Data analysis + +CAT_LICENSE: # Passed + value: https://spdx.org/licenses/BSD-3-Clause + +CAT_VERSION: v1.3 # Passed + +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.4701488 # Passed + +CAT_DESCRIPTION: Gammapy analyzes gamma-ray data and creates sky images, spectra and lightcurves, from event lists and instrument response information; it can also determine the position, morphology and spectra of gamma-ray sources. It is used to analyze data from H.E.S.S., Fermi-LAT, HAWC, and the Cherenkov Telescope Array (CTA). # Passed + +CAT_REQUIREMENTS: # Passed + value: numpy>=1.21 + name: numpy + version: ">=1.21" + type: Software_application + +CAT_AUTHORS: # Passed + value: Fabio Acero + type: String \ No newline at end of file diff --git a/src/somef_core/test/test_data/expected/r3broot2 2.yaml b/src/somef_core/test/test_data/expected/r3broot2 2.yaml new file mode 100644 index 0000000..8953872 --- /dev/null +++ b/src/somef_core/test/test_data/expected/r3broot2 2.yaml @@ -0,0 +1,44 @@ +CAT_NAME: R3BRoot # Passed +CAT_CODE_REPOSITORY: https://github.com/R3BRootGroup/R3BRoot # Passed +CAT_ISSUE_TRACKER: https://github.com/R3BRootGroup/R3BRoot/issues # Passed +CAT_DATE_CREATED: "2009-04-14" # Passed +CAT_DATE_UPDATED: "2024-12-06" # Passed +CAT_DATE_PUBLISHED: "2009-08-01" # Passed +CAT_DOWNLOAD_URL: https://github.com/R3BRootGroup/R3BRoot/archive/refs/tags/dec24.tar.gz # Passed +CAT_README_URL: # Passed + value: "https://github.com/R3BRootGroup/R3BRoot/blob/dev/README.md" + +CAT_KEYWORDS: # Passed + - Geant4 + - c-plus-plus + - cmake + - vmc + - modular + - Track reconstruction + - Simulation + - Data analysis + - Structure and dynamics of nuclei + - Nuclear reactions + - Nuclear fission + - Hypernuclei + - Equation of state + - Short range NN correlations + - R3B experiments + - GSI/FAIR facility +CAT_LICENSE: # Passed + value: https://spdx.org/licenses/GPL-3.0 +CAT_VERSION: 24.0.0 # Passed +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.5549469 # Passed +CAT_DESCRIPTION: Software for simulations and data analysis of Reactions with Relativistic Radioactive Beams (R3B) experiments at GSI/FAIR # Passed +CAT_REQUIREMENTS: # Passed + value: FairRoot, FairSoft + name: Null + version: Null +CAT_AUTHORS: # Passed + value: "Jose Luis Rodr\u00edguez-S\u00e1nchez" + type: String + email: j.l.rodriguez.sanchez@udc.es + affiliation: "CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain" # Passed + identifier: https://orcid.org/0000-0002-4702-5294 + +CAT_CITATION: https://doi.org/10.1088/1742-6596/523/1/012034 # Passed diff --git a/src/somef_core/test/test_data/expected/r3broot2.yaml b/src/somef_core/test/test_data/expected/r3broot2.yaml new file mode 100644 index 0000000..8953872 --- /dev/null +++ b/src/somef_core/test/test_data/expected/r3broot2.yaml @@ -0,0 +1,44 @@ +CAT_NAME: R3BRoot # Passed +CAT_CODE_REPOSITORY: https://github.com/R3BRootGroup/R3BRoot # Passed +CAT_ISSUE_TRACKER: https://github.com/R3BRootGroup/R3BRoot/issues # Passed +CAT_DATE_CREATED: "2009-04-14" # Passed +CAT_DATE_UPDATED: "2024-12-06" # Passed +CAT_DATE_PUBLISHED: "2009-08-01" # Passed +CAT_DOWNLOAD_URL: https://github.com/R3BRootGroup/R3BRoot/archive/refs/tags/dec24.tar.gz # Passed +CAT_README_URL: # Passed + value: "https://github.com/R3BRootGroup/R3BRoot/blob/dev/README.md" + +CAT_KEYWORDS: # Passed + - Geant4 + - c-plus-plus + - cmake + - vmc + - modular + - Track reconstruction + - Simulation + - Data analysis + - Structure and dynamics of nuclei + - Nuclear reactions + - Nuclear fission + - Hypernuclei + - Equation of state + - Short range NN correlations + - R3B experiments + - GSI/FAIR facility +CAT_LICENSE: # Passed + value: https://spdx.org/licenses/GPL-3.0 +CAT_VERSION: 24.0.0 # Passed +CAT_IDENTIFIER: https://doi.org/10.5281/zenodo.5549469 # Passed +CAT_DESCRIPTION: Software for simulations and data analysis of Reactions with Relativistic Radioactive Beams (R3B) experiments at GSI/FAIR # Passed +CAT_REQUIREMENTS: # Passed + value: FairRoot, FairSoft + name: Null + version: Null +CAT_AUTHORS: # Passed + value: "Jose Luis Rodr\u00edguez-S\u00e1nchez" + type: String + email: j.l.rodriguez.sanchez@udc.es + affiliation: "CITENI, Industrial Campus of Ferrol, University of Coruña, 15403 Ferrol, Spain" # Passed + identifier: https://orcid.org/0000-0002-4702-5294 + +CAT_CITATION: https://doi.org/10.1088/1742-6596/523/1/012034 # Passed diff --git a/src/somef_core/test/test_data/export_test copy.json b/src/somef_core/test/test_data/export_test copy.json new file mode 100644 index 0000000..4aa5dcc --- /dev/null +++ b/src/somef_core/test/test_data/export_test copy.json @@ -0,0 +1,142 @@ +{ + "code_repository": [ + "https://github.com/dgarijo/Widoco" + ], + "owner": + { + "value": "dgarijo", + "type": "Person" + + }, + "date_created": [ + "2013-07-15T15:51:51Z" + ], + "date_updated": [ + "2022-12-18T20:05:20Z" + ], + "license": + { + "spdx_id": "Apache-2.0", + "name": "Apache License 2.0", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE" + }, + "description": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html))\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO.\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. \n", + "There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. \n* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend.\n* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ; is used for lists (for instance first author; second author; third author).\n \n", + "For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository.\n \n", + "Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release.\n \n" + ], + "name": [ + "Widoco" + ], + "full_name": [ + "dgarijo/Widoco" + ], + "issue_tracker": [ + "https://api.github.com/repos/dgarijo/Widoco/issues" + ], + "forks_url": [ + "https://api.github.com/repos/dgarijo/Widoco/forks" + ], + "stargazers_count": [ + 204 + ], + "keywords": [ + "documentation, metadata, ontology, ontology-diagram, ontology-evaluation, wizard" + ], + "forks_count": [ + 73 + ], + "download_url": [ + "https://github.com/dgarijo/Widoco/releases" + ], + "programming_languages": [ + "Java", + "XSLT", + "CSS", + "JavaScript", + "HTML", + "Dockerfile" + ], + "releases_ids": [ + 3701886, 3701887 + ], + "releases": [ + { + "type": "Release", + "release_id": 3701886, + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "tag": "v1.4.17", + "name": "WIDOCO 1.4.17: Update OOPS! Web service. GitHub actions", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version fixes OOPS! (newest URL) and sets up GitHub actions so users with different versions of Java can use Widoco.\r\n\r\n## What's Changed\r\n* update readme and pom with proper versions by @dgarijo in https://github.com/dgarijo/Widoco/pull/502\r\n* switch import fonts to always use https scheme by @renefritze in https://github.com/dgarijo/Widoco/pull/509\r\n* [ci] setup gh actions + dependabot by @renefritze in https://github.com/dgarijo/Widoco/pull/507\r\n* Github actions set up by @renefritze by @dgarijo in https://github.com/dgarijo/Widoco/pull/512\r\n\r\n## New Contributors\r\n* @renefritze made their first contribution in https://github.com/dgarijo/Widoco/pull/509\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.16...v1.4.17", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.17", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.17", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.17", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "date_created": "2022-04-19T10:57:14Z", + "date_published": "2022-04-19T11:10:33Z" + }, + { + "type": "Release", + "release_id": 3701887, + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "tag": "v1.4.16", + "name": "WIDOCO 1.4.16: Support for German and Dutch", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO includes support for German and Dutch (thanks to Flores Bakker), extraction of metadata from local authors and organizations URIs (if you describe authors and their organizations in your ontology, WIDOCO will automatically detect it) and additional support for adding images in your documentation.\r\n \r\n## What's Changed\r\n* Fix/duplicate namespace declarations by @pmcb55 in https://github.com/dgarijo/Widoco/pull/471\r\n* Only show legend entries if relevant by @pmcb55 in https://github.com/dgarijo/Widoco/pull/472\r\n* Dockerize project by @ccamel in https://github.com/dgarijo/Widoco/pull/479\r\n* Support for adding images with GUI by @dgarijo in https://github.com/dgarijo/Widoco/pull/492\r\n* Fix #262 by @dgarijo in https://github.com/dgarijo/Widoco/pull/493\r\n* German translation by @JohnnyMoonlight in https://github.com/dgarijo/Widoco/pull/494\r\n* Support for it and de by @dgarijo in https://github.com/dgarijo/Widoco/pull/495\r\n* Fix #498 by @engapa in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n## New Contributors\r\n* @ccamel made their first contribution in https://github.com/dgarijo/Widoco/pull/479\r\n* @JohnnyMoonlight made their first contribution in https://github.com/dgarijo/Widoco/pull/494\r\n* @engapa made their first contribution in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.15...v1.4.16", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.16", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.16", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.16", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "date_created": "2022-03-17T21:38:26Z", + "date_published": "2022-03-17T22:13:15Z" + } + ], + "contributing_guidelines": [ + "## Contribution guidelines\nContributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n" + ], + "has_build_file": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/Dockerfile" + ], + "readme_url": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + ], + "citation": [ + "https://doi.org/10.1007/978-3-319-68204-4_9" + ], + "download": [ + "##Downloading the executable\nTo download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest).\n" + ], + "requirements": [ + "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.16\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n", + "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an Unsupported major.minor version 52.0 exception when executing the JAR file.\n" + ], + "usage": [ + "##Examples\nExamples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/)\n##GUI Tutorial\nA tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) \n##JAR execution\nDownload the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file.\n\nYou may also execute WIDOCO through the command line. Usage:\n```bash\njava -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS]\n```\n##Docker execution\nFirst build the image using the `Dockerfile` in project folder:\n\n```bash\ndocker build -t dgarijo/widoco .\n```\n\nYou can now execute WIDOCO through the command line. Usage:\n\n```bash\ndocker run -ti --rm dgarijo/widoco [OPTIONS]\n```\n\nIf you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container\nwith host directories. For instance:\n\n```bash\ndocker run -ti --rm \\\n -v `pwd`/test:/usr/local/widoco/in \\\n -v `pwd`/target/generated-doc:/usr/local/widoco/out \\\n dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll\n```\n##Options\n`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI\n\n`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile\n\n`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is \"myDocumentation\"\n\n`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata\n\n`-getOntologyMetadata`: Extract ontology metadata from the given ontology\n\n`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/)\n\n`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution)\n\n`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists.\n\n`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology\n\n`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila).\n\n`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by -). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es\n\n`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not.\n\n`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server.\n\n`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation.\n\n`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled.\n\n`-ignoreIndividuals`: Individuals will not be included in the documentation.\n\n`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included)\n\n`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234\n\n`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed.\n\n`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented.\n\n`-rewriteBase PATH`: Change the default rewrite base path. The default value is /. This flag can only be used with the htaccess option.\n\n`-excludeIntroduction`: Skip the introduction section in the documentation.\n\n`-uniteSections`: Write all HTML sections into a single HTML document.\n\n`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections).\n\n`--help`: Shows a help message and exits.\n\n" + ], + "documentation": ["https://readthedocslink.com/widoco"], + "application_domain": [ + "Semantic web" + ], + "identifier": [ + "https://zenodo.org/badge/latestdoi/11427075" + ], + "full_title": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "repository_status": [ + "https://www.repostatus.org/#active" + ], + "logo": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png" + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/export_test.json b/src/somef_core/test/test_data/export_test.json new file mode 100644 index 0000000..4aa5dcc --- /dev/null +++ b/src/somef_core/test/test_data/export_test.json @@ -0,0 +1,142 @@ +{ + "code_repository": [ + "https://github.com/dgarijo/Widoco" + ], + "owner": + { + "value": "dgarijo", + "type": "Person" + + }, + "date_created": [ + "2013-07-15T15:51:51Z" + ], + "date_updated": [ + "2022-12-18T20:05:20Z" + ], + "license": + { + "spdx_id": "Apache-2.0", + "name": "Apache License 2.0", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE" + }, + "description": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html))\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO.\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. \n", + "There are two alternative ways for making WIDOCO get your vocabulary metadata annotations and use them automatically to document the ontology. \n* The recommended way: add them in your OWL file. For guidelines on which ones to include, follow our [best practices document](https://w3id.org/widoco/bestPractices), which indicates which ones we recommend.\n* Alternatively, edit the project properties of /config/config.properties. This is a key-value pair file with metadata properties. Some people consider it easier than adding the property annotations to the OWL file, although I recommend doing the former option. Note that the character ; is used for lists (for instance first author; second author; third author).\n \n", + "For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository.\n \n", + "Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release.\n \n" + ], + "name": [ + "Widoco" + ], + "full_name": [ + "dgarijo/Widoco" + ], + "issue_tracker": [ + "https://api.github.com/repos/dgarijo/Widoco/issues" + ], + "forks_url": [ + "https://api.github.com/repos/dgarijo/Widoco/forks" + ], + "stargazers_count": [ + 204 + ], + "keywords": [ + "documentation, metadata, ontology, ontology-diagram, ontology-evaluation, wizard" + ], + "forks_count": [ + 73 + ], + "download_url": [ + "https://github.com/dgarijo/Widoco/releases" + ], + "programming_languages": [ + "Java", + "XSLT", + "CSS", + "JavaScript", + "HTML", + "Dockerfile" + ], + "releases_ids": [ + 3701886, 3701887 + ], + "releases": [ + { + "type": "Release", + "release_id": 3701886, + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "tag": "v1.4.17", + "name": "WIDOCO 1.4.17: Update OOPS! Web service. GitHub actions", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version fixes OOPS! (newest URL) and sets up GitHub actions so users with different versions of Java can use Widoco.\r\n\r\n## What's Changed\r\n* update readme and pom with proper versions by @dgarijo in https://github.com/dgarijo/Widoco/pull/502\r\n* switch import fonts to always use https scheme by @renefritze in https://github.com/dgarijo/Widoco/pull/509\r\n* [ci] setup gh actions + dependabot by @renefritze in https://github.com/dgarijo/Widoco/pull/507\r\n* Github actions set up by @renefritze by @dgarijo in https://github.com/dgarijo/Widoco/pull/512\r\n\r\n## New Contributors\r\n* @renefritze made their first contribution in https://github.com/dgarijo/Widoco/pull/509\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.16...v1.4.17", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.17", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.17", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.17", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/64724790", + "date_created": "2022-04-19T10:57:14Z", + "date_published": "2022-04-19T11:10:33Z" + }, + { + "type": "Release", + "release_id": 3701887, + "value": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "tag": "v1.4.16", + "name": "WIDOCO 1.4.16: Support for German and Dutch", + "author": { + "name": "dgarijo", + "type": "User" + }, + "description": "This version of WIDOCO includes support for German and Dutch (thanks to Flores Bakker), extraction of metadata from local authors and organizations URIs (if you describe authors and their organizations in your ontology, WIDOCO will automatically detect it) and additional support for adding images in your documentation.\r\n \r\n## What's Changed\r\n* Fix/duplicate namespace declarations by @pmcb55 in https://github.com/dgarijo/Widoco/pull/471\r\n* Only show legend entries if relevant by @pmcb55 in https://github.com/dgarijo/Widoco/pull/472\r\n* Dockerize project by @ccamel in https://github.com/dgarijo/Widoco/pull/479\r\n* Support for adding images with GUI by @dgarijo in https://github.com/dgarijo/Widoco/pull/492\r\n* Fix #262 by @dgarijo in https://github.com/dgarijo/Widoco/pull/493\r\n* German translation by @JohnnyMoonlight in https://github.com/dgarijo/Widoco/pull/494\r\n* Support for it and de by @dgarijo in https://github.com/dgarijo/Widoco/pull/495\r\n* Fix #498 by @engapa in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n## New Contributors\r\n* @ccamel made their first contribution in https://github.com/dgarijo/Widoco/pull/479\r\n* @JohnnyMoonlight made their first contribution in https://github.com/dgarijo/Widoco/pull/494\r\n* @engapa made their first contribution in https://github.com/dgarijo/Widoco/pull/500\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.15...v1.4.16", + "tarball_url": "https://api.github.com/repos/dgarijo/Widoco/tarball/v1.4.16", + "zipball_url": "https://api.github.com/repos/dgarijo/Widoco/zipball/v1.4.16", + "html_url": "https://github.com/dgarijo/Widoco/releases/tag/v1.4.16", + "url": "https://api.github.com/repos/dgarijo/Widoco/releases/62144298", + "date_created": "2022-03-17T21:38:26Z", + "date_published": "2022-03-17T22:13:15Z" + } + ], + "contributing_guidelines": [ + "## Contribution guidelines\nContributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n" + ], + "has_build_file": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/Dockerfile" + ], + "readme_url": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + ], + "citation": [ + "https://doi.org/10.1007/978-3-319-68204-4_9" + ], + "download": [ + "##Downloading the executable\nTo download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest).\n" + ], + "requirements": [ + "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.16\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n", + "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an Unsupported major.minor version 52.0 exception when executing the JAR file.\n" + ], + "usage": [ + "##Examples\nExamples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/)\n##GUI Tutorial\nA tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) \n##JAR execution\nDownload the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file.\n\nYou may also execute WIDOCO through the command line. Usage:\n```bash\njava -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS]\n```\n##Docker execution\nFirst build the image using the `Dockerfile` in project folder:\n\n```bash\ndocker build -t dgarijo/widoco .\n```\n\nYou can now execute WIDOCO through the command line. Usage:\n\n```bash\ndocker run -ti --rm dgarijo/widoco [OPTIONS]\n```\n\nIf you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container\nwith host directories. For instance:\n\n```bash\ndocker run -ti --rm \\\n -v `pwd`/test:/usr/local/widoco/in \\\n -v `pwd`/target/generated-doc:/usr/local/widoco/out \\\n dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll\n```\n##Options\n`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI\n\n`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile\n\n`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is \"myDocumentation\"\n\n`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata\n\n`-getOntologyMetadata`: Extract ontology metadata from the given ontology\n\n`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/)\n\n`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution)\n\n`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists.\n\n`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology\n\n`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila).\n\n`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by -). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es\n\n`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not.\n\n`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server.\n\n`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation.\n\n`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled.\n\n`-ignoreIndividuals`: Individuals will not be included in the documentation.\n\n`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included)\n\n`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234\n\n`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed.\n\n`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented.\n\n`-rewriteBase PATH`: Change the default rewrite base path. The default value is /. This flag can only be used with the htaccess option.\n\n`-excludeIntroduction`: Skip the introduction section in the documentation.\n\n`-uniteSections`: Write all HTML sections into a single HTML document.\n\n`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections).\n\n`--help`: Shows a help message and exits.\n\n" + ], + "documentation": ["https://readthedocslink.com/widoco"], + "application_domain": [ + "Semantic web" + ], + "identifier": [ + "https://zenodo.org/badge/latestdoi/11427075" + ], + "full_title": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "repository_status": [ + "https://www.repostatus.org/#active" + ], + "logo": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png" + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/package_neors.json b/src/somef_core/test/test_data/package_neors.json index 39b455e..ecb6951 100644 --- a/src/somef_core/test/test_data/package_neors.json +++ b/src/somef_core/test/test_data/package_neors.json @@ -17,5 +17,13 @@ "bugs": { "url": "https://github.com/fangq/jsonlab/issues" }, - "homepage": "https://iso2mesh.sf.net/jsonlab/" + "homepage": "https://iso2mesh.sf.net/jsonlab/", + "dependencies": { + "foo": "1.0.0 - 2.9999.9999", + "bar": ">=1.0.2 <2.1.2", + "baz": ">1.0.2 <=2.3.4" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } } diff --git a/src/somef_core/test/test_data/package_npm.json b/src/somef_core/test/test_data/package_npm.json new file mode 100644 index 0000000..b242ece --- /dev/null +++ b/src/somef_core/test/test_data/package_npm.json @@ -0,0 +1,258 @@ +{ + "version": "11.6.2", + "name": "npm", + "description": "a package manager for JavaScript", + "workspaces": [ + "docs", + "smoke-tests", + "mock-globals", + "mock-registry", + "workspaces/*" + ], + "files": [ + "bin/", + "lib/", + "index.js", + "docs/content/", + "docs/output/", + "man/" + ], + "keywords": [ + "install", + "modules", + "package manager", + "package.json" + ], + "homepage": "https://docs.npmjs.com/", + "author": "GitHub Inc.", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/cli.git" + }, + "bugs": { + "url": "https://github.com/npm/cli/issues" + }, + "directories": { + "doc": "./doc", + "man": "./man" + }, + "main": "./index.js", + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "exports": { + ".": [ + { + "default": "./index.js" + }, + "./index.js" + ], + "./package.json": "./package.json" + }, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^9.1.6", + "@npmcli/config": "^10.4.2", + "@npmcli/fs": "^4.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/package-json": "^7.0.1", + "@npmcli/promise-spawn": "^8.0.3", + "@npmcli/redact": "^3.2.2", + "@npmcli/run-script": "^10.0.0", + "@sigstore/tuf": "^4.0.0", + "abbrev": "^3.0.1", + "archy": "~1.0.0", + "cacache": "^20.0.1", + "chalk": "^5.6.2", + "ci-info": "^4.3.1", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^11.0.3", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^9.0.2", + "ini": "^5.0.0", + "init-package-json": "^8.2.2", + "is-cidr": "^6.0.1", + "json-parse-even-better-errors": "^4.0.0", + "libnpmaccess": "^10.0.3", + "libnpmdiff": "^8.0.9", + "libnpmexec": "^10.1.8", + "libnpmfund": "^7.0.9", + "libnpmorg": "^8.0.1", + "libnpmpack": "^9.0.9", + "libnpmpublish": "^11.1.2", + "libnpmsearch": "^9.0.1", + "libnpmteam": "^8.0.2", + "libnpmversion": "^8.0.2", + "make-fetch-happen": "^15.0.2", + "minimatch": "^10.0.3", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^11.4.2", + "nopt": "^8.1.0", + "npm-audit-report": "^6.0.0", + "npm-install-checks": "^7.1.2", + "npm-package-arg": "^13.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-profile": "^12.0.0", + "npm-registry-fetch": "^19.0.0", + "npm-user-validate": "^3.0.0", + "p-map": "^7.0.3", + "pacote": "^21.0.3", + "parse-conflict-json": "^4.0.0", + "proc-log": "^5.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^4.1.0", + "semver": "^7.7.3", + "spdx-expression-parse": "^4.0.0", + "ssri": "^12.0.0", + "supports-color": "^10.2.2", + "tar": "^7.5.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^2.0.2", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^6.0.2", + "which": "^5.0.0" + }, + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which" + ], + "devDependencies": { + "@npmcli/docs": "^1.0.0", + "@npmcli/eslint-config": "^5.1.0", + "@npmcli/git": "^7.0.0", + "@npmcli/mock-globals": "^1.0.0", + "@npmcli/mock-registry": "^1.0.0", + "@npmcli/template-oss": "4.25.1", + "@tufjs/repo-mock": "^4.0.0", + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "ajv-formats-draft2019": "^1.6.1", + "cli-table3": "^0.6.4", + "diff": "^8.0.2", + "nock": "^13.4.0", + "npm-packlist": "^10.0.2", + "remark": "^15.0.1", + "remark-gfm": "^4.0.1", + "remark-github": "^12.0.0", + "rimraf": "^6.0.1", + "spawk": "^1.7.1", + "tap": "^16.3.9" + }, + "scripts": { + "dependencies": "node scripts/bundle-and-gitignore-deps.js && node scripts/dependency-graph.js", + "dumpconf": "env | grep npm | sort | uniq", + "licenses": "npx licensee --production --errors-only", + "test": "tap", + "test:nocolor": "CI=true tap -Rclassic", + "test-all": "node . run test --workspaces --include-workspace-root --if-present", + "snap": "tap", + "prepack": "node . run build -w docs", + "posttest": "node . run lint", + "lint": "node . run eslint", + "lintfix": "node . run eslint -- --fix", + "lint-all": "node . run lint --workspaces --include-workspace-root --if-present", + "resetdeps": "node scripts/resetdeps.js", + "rp-pull-request": "node scripts/update-authors.js", + "postlint": "template-oss-check", + "template-oss-apply": "template-oss-apply --force", + "eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"" + }, + "tap": { + "test-env": [ + "LC_ALL=sk" + ], + "timeout": 600, + "nyc-arg": [ + "--exclude", + "docs/**", + "--exclude", + "smoke-tests/**", + "--exclude", + "mock-globals/**", + "--exclude", + "mock-registry/**", + "--exclude", + "workspaces/**", + "--exclude", + "tap-snapshots/**" + ], + "test-ignore": "^(docs|smoke-tests|mock-globals|mock-registry|workspaces)/" + }, + "templateOSS": { + "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits could be overwritten.", + "version": "4.25.1", + "content": "./scripts/template-oss/root.js" + }, + "license": "Artistic-2.0", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile b/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile new file mode 100644 index 0000000..3c0d1ea --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile @@ -0,0 +1,14 @@ +FROM alpine:3.23 + +LABEL org.opencontainers.image.authors="FairwindsOps, Inc." \ + org.opencontainers.image.vendor="FairwindsOps, Inc." \ + org.opencontainers.image.title="Nova" \ + org.opencontainers.image.description="Nova is a cli tool to find outdated or deprecated Helm charts running in your Kubernetes cluster." \ + org.opencontainers.image.documentation="https://nova.docs.fairwinds.com/" \ + org.opencontainers.image.source="https://github.com/FairwindsOps/nova" \ + org.opencontainers.image.url="https://github.com/FairwindsOps/nova" \ + org.opencontainers.image.licenses="Apache License 2.0" + +USER nobody +COPY nova / +CMD ["/nova"] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile 2 b/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile 2 new file mode 100644 index 0000000..3c0d1ea --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Fairwinds/Dockerfile 2 @@ -0,0 +1,14 @@ +FROM alpine:3.23 + +LABEL org.opencontainers.image.authors="FairwindsOps, Inc." \ + org.opencontainers.image.vendor="FairwindsOps, Inc." \ + org.opencontainers.image.title="Nova" \ + org.opencontainers.image.description="Nova is a cli tool to find outdated or deprecated Helm charts running in your Kubernetes cluster." \ + org.opencontainers.image.documentation="https://nova.docs.fairwinds.com/" \ + org.opencontainers.image.source="https://github.com/FairwindsOps/nova" \ + org.opencontainers.image.url="https://github.com/FairwindsOps/nova" \ + org.opencontainers.image.licenses="Apache License 2.0" + +USER nobody +COPY nova / +CMD ["/nova"] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Flux.jl/Project 2.toml b/src/somef_core/test/test_data/repositories/Flux.jl/Project 2.toml new file mode 100644 index 0000000..2458862 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Flux.jl/Project 2.toml @@ -0,0 +1,71 @@ +name = "Flux" +uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c" +version = "0.16.5" + +[deps] +Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" +EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" +Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +MLCore = "c2834f40-e789-41da-a90e-33b280584a8c" +MLDataDevices = "7e8f7934-dd98-4c1a-8fe8-92b47a384d40" +MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54" +MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" +OneHotArrays = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f" +Optimisers = "3bd65402-5787-11e9-1adc-39752487f4e2" +Preferences = "21216c6a-2e73-6563-6e65-726566657250" +ProgressLogging = "33c8b6b6-d38a-422a-b730-caa89a2f386c" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[weakdeps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" +NCCL = "3fe64909-d7a1-4096-9b7d-7a0f12cf0f6b" +cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" + +[extensions] +FluxAMDGPUExt = "AMDGPU" +FluxCUDAExt = "CUDA" +FluxCUDAcuDNNExt = ["CUDA", "cuDNN"] +FluxEnzymeExt = "Enzyme" +FluxMPIExt = "MPI" +FluxMPINCCLExt = ["CUDA", "MPI", "NCCL"] + +[compat] +AMDGPU = "1, 2" +Adapt = "4" +CUDA = "5" +ChainRulesCore = "1.12" +Compat = "4.10.0" +Enzyme = "0.13" +EnzymeCore = "0.7.7, 0.8.4" +Functors = "0.5" +MLCore = "1.0.0" +MLDataDevices = "1.4.2" +MLUtils = "0.4" +MPI = "0.20.19" +MacroTools = "0.5" +NCCL = "0.1.1" +NNlib = "0.9.22" +OneHotArrays = "0.2.4" +Optimisers = "0.4.1" +Preferences = "1" +ProgressLogging = "0.1" +Reexport = "1.0" +Setfield = "1.1" +SpecialFunctions = "2.1.2" +Statistics = "1" +Zygote = "0.6.67, 0.7" +cuDNN = "1" +julia = "1.10" diff --git a/src/somef_core/test/test_data/repositories/Flux.jl/Project.toml b/src/somef_core/test/test_data/repositories/Flux.jl/Project.toml new file mode 100644 index 0000000..2458862 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Flux.jl/Project.toml @@ -0,0 +1,71 @@ +name = "Flux" +uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c" +version = "0.16.5" + +[deps] +Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +Compat = "34da2185-b29b-5c13-b0c7-acf172513d20" +EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" +Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +MLCore = "c2834f40-e789-41da-a90e-33b280584a8c" +MLDataDevices = "7e8f7934-dd98-4c1a-8fe8-92b47a384d40" +MLUtils = "f1d291b0-491e-4a28-83b9-f70985020b54" +MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" +OneHotArrays = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f" +Optimisers = "3bd65402-5787-11e9-1adc-39752487f4e2" +Preferences = "21216c6a-2e73-6563-6e65-726566657250" +ProgressLogging = "33c8b6b6-d38a-422a-b730-caa89a2f386c" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" +Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46" +SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" +Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[weakdeps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" +Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" +MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" +NCCL = "3fe64909-d7a1-4096-9b7d-7a0f12cf0f6b" +cuDNN = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd" + +[extensions] +FluxAMDGPUExt = "AMDGPU" +FluxCUDAExt = "CUDA" +FluxCUDAcuDNNExt = ["CUDA", "cuDNN"] +FluxEnzymeExt = "Enzyme" +FluxMPIExt = "MPI" +FluxMPINCCLExt = ["CUDA", "MPI", "NCCL"] + +[compat] +AMDGPU = "1, 2" +Adapt = "4" +CUDA = "5" +ChainRulesCore = "1.12" +Compat = "4.10.0" +Enzyme = "0.13" +EnzymeCore = "0.7.7, 0.8.4" +Functors = "0.5" +MLCore = "1.0.0" +MLDataDevices = "1.4.2" +MLUtils = "0.4" +MPI = "0.20.19" +MacroTools = "0.5" +NCCL = "0.1.1" +NNlib = "0.9.22" +OneHotArrays = "0.2.4" +Optimisers = "0.4.1" +Preferences = "1" +ProgressLogging = "0.1" +Reexport = "1.0" +Setfield = "1.1" +SpecialFunctions = "2.1.2" +Statistics = "1" +Zygote = "0.6.67, 0.7" +cuDNN = "1" +julia = "1.10" diff --git a/src/somef_core/test/test_data/repositories/Pluto.jl/Project 2.toml b/src/somef_core/test/test_data/repositories/Pluto.jl/Project 2.toml new file mode 100644 index 0000000..7472541 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Pluto.jl/Project 2.toml @@ -0,0 +1,84 @@ +name = "Pluto" +uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781" +license = "MIT" +authors = ["Fons van der Plas "] +version = "0.20.20" + +[deps] +Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +Configurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +ExpressionExplorer = "21656369-7473-754a-2065-74616d696c43" +FileWatching = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +GracefulPkg = "828d9ff0-206c-6161-646e-6576656f7244" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36" +MIMEs = "6c6e2e6c-3030-632d-7369-2d6c69616d65" +Malt = "36869731-bdee-424d-aa32-cab38c994e3b" +Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" +MsgPack = "99f44e22-a591-53d1-9472-aa23ef4bd671" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlutoDependencyExplorer = "72656b73-756c-7461-726b-72656b6b696b" +PrecompileSignatures = "91cefc8d-f054-46dc-8f8c-26e11d7c5411" +PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RegistryInstances = "2792f1a3-b283-48e8-9a74-f99dce5104f3" +RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" +Scratch = "6c6a2e73-6563-6170-7368-637461726353" +Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" +TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[compat] +Base64 = "1" +Configurations = "0.15, 0.16, 0.17" +Dates = "0, 1" +Downloads = "1" +ExpressionExplorer = "0.5, 0.6, 1" +FileWatching = "1" +GracefulPkg = "2" +HTTP = "^1.10.17" +HypertextLiteral = "0.7, 0.8, 0.9" +InteractiveUtils = "1" +LRUCache = "1.6.2" +Logging = "1" +LoggingExtras = "0.4, 1" +MIMEs = "0.1, 1" +Malt = "1.1" +Markdown = "1" +MsgPack = "1.1" +Pkg = "1" +PlutoDependencyExplorer = "~1.2" +PrecompileSignatures = "3" +PrecompileTools = "~1.2, ~1.3" +REPL = "1" +RegistryInstances = "0.1" +RelocatableFolders = "0.1, 0.2, 0.3, 1" +SHA = "0.7, 1" +Scratch = "1.1" +Sockets = "1" +TOML = "1" +Tables = "1" +URIs = "1.3" +UUIDs = "1" +julia = "^1.10" + +[extras] +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" + +[targets] +test = ["DataFrames", "OffsetArrays", "Sockets", "Test", "TimerOutputs", "Memoize"] diff --git a/src/somef_core/test/test_data/repositories/Pluto.jl/Project.toml b/src/somef_core/test/test_data/repositories/Pluto.jl/Project.toml new file mode 100644 index 0000000..7472541 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Pluto.jl/Project.toml @@ -0,0 +1,84 @@ +name = "Pluto" +uuid = "c3e4b0f8-55cb-11ea-2926-15256bba5781" +license = "MIT" +authors = ["Fons van der Plas "] +version = "0.20.20" + +[deps] +Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +Configurations = "5218b696-f38b-4ac9-8b61-a12ec717816d" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +ExpressionExplorer = "21656369-7473-754a-2065-74616d696c43" +FileWatching = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +GracefulPkg = "828d9ff0-206c-6161-646e-6576656f7244" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +HypertextLiteral = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2" +InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36" +MIMEs = "6c6e2e6c-3030-632d-7369-2d6c69616d65" +Malt = "36869731-bdee-424d-aa32-cab38c994e3b" +Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" +MsgPack = "99f44e22-a591-53d1-9472-aa23ef4bd671" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +PlutoDependencyExplorer = "72656b73-756c-7461-726b-72656b6b696b" +PrecompileSignatures = "91cefc8d-f054-46dc-8f8c-26e11d7c5411" +PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +RegistryInstances = "2792f1a3-b283-48e8-9a74-f99dce5104f3" +RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" +Scratch = "6c6a2e73-6563-6170-7368-637461726353" +Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" +TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[compat] +Base64 = "1" +Configurations = "0.15, 0.16, 0.17" +Dates = "0, 1" +Downloads = "1" +ExpressionExplorer = "0.5, 0.6, 1" +FileWatching = "1" +GracefulPkg = "2" +HTTP = "^1.10.17" +HypertextLiteral = "0.7, 0.8, 0.9" +InteractiveUtils = "1" +LRUCache = "1.6.2" +Logging = "1" +LoggingExtras = "0.4, 1" +MIMEs = "0.1, 1" +Malt = "1.1" +Markdown = "1" +MsgPack = "1.1" +Pkg = "1" +PlutoDependencyExplorer = "~1.2" +PrecompileSignatures = "3" +PrecompileTools = "~1.2, ~1.3" +REPL = "1" +RegistryInstances = "0.1" +RelocatableFolders = "0.1, 0.2, 0.3, 1" +SHA = "0.7, 1" +Scratch = "1.1" +Sockets = "1" +TOML = "1" +Tables = "1" +URIs = "1.3" +UUIDs = "1" +julia = "^1.10" + +[extras] +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Memoize = "c03570c3-d221-55d1-a50c-7939bbd78826" +OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +Sockets = "6462fe0b-24de-5631-8697-dd941f90decc" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" + +[targets] +test = ["DataFrames", "OffsetArrays", "Sockets", "Test", "TimerOutputs", "Memoize"] diff --git a/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile b/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile new file mode 100644 index 0000000..2b74c92 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile @@ -0,0 +1,31 @@ +ARG ARCH="amd64" +ARG OS="linux" +FROM quay.io/prometheus/busybox-${OS}-${ARCH}:latest +LABEL maintainer="The Prometheus Authors " +LABEL org.opencontainers.image.authors="The Prometheus Authors" \ + org.opencontainers.image.vendor="Prometheus" \ + org.opencontainers.image.title="Prometheus" \ + org.opencontainers.image.description="The Prometheus monitoring system and time series database" \ + org.opencontainers.image.source="https://github.com/prometheus/prometheus" \ + org.opencontainers.image.url="https://github.com/prometheus/prometheus" \ + org.opencontainers.image.documentation="https://prometheus.io/docs" \ + org.opencontainers.image.licenses="Apache License 2.0" + +ARG ARCH="amd64" +ARG OS="linux" +COPY .build/${OS}-${ARCH}/prometheus /bin/prometheus +COPY .build/${OS}-${ARCH}/promtool /bin/promtool +COPY documentation/examples/prometheus.yml /etc/prometheus/prometheus.yml +COPY LICENSE /LICENSE +COPY NOTICE /NOTICE +COPY npm_licenses.tar.bz2 /npm_licenses.tar.bz2 + +WORKDIR /prometheus +RUN chown -R nobody:nobody /etc/prometheus /prometheus && chmod g+w /prometheus + +USER nobody +EXPOSE 9090 +VOLUME [ "/prometheus" ] +ENTRYPOINT [ "/bin/prometheus" ] +CMD [ "--config.file=/etc/prometheus/prometheus.yml", \ + "--storage.tsdb.path=/prometheus" ] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile 2 b/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile 2 new file mode 100644 index 0000000..2b74c92 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Prometeus/Dockerfile 2 @@ -0,0 +1,31 @@ +ARG ARCH="amd64" +ARG OS="linux" +FROM quay.io/prometheus/busybox-${OS}-${ARCH}:latest +LABEL maintainer="The Prometheus Authors " +LABEL org.opencontainers.image.authors="The Prometheus Authors" \ + org.opencontainers.image.vendor="Prometheus" \ + org.opencontainers.image.title="Prometheus" \ + org.opencontainers.image.description="The Prometheus monitoring system and time series database" \ + org.opencontainers.image.source="https://github.com/prometheus/prometheus" \ + org.opencontainers.image.url="https://github.com/prometheus/prometheus" \ + org.opencontainers.image.documentation="https://prometheus.io/docs" \ + org.opencontainers.image.licenses="Apache License 2.0" + +ARG ARCH="amd64" +ARG OS="linux" +COPY .build/${OS}-${ARCH}/prometheus /bin/prometheus +COPY .build/${OS}-${ARCH}/promtool /bin/promtool +COPY documentation/examples/prometheus.yml /etc/prometheus/prometheus.yml +COPY LICENSE /LICENSE +COPY NOTICE /NOTICE +COPY npm_licenses.tar.bz2 /npm_licenses.tar.bz2 + +WORKDIR /prometheus +RUN chown -R nobody:nobody /etc/prometheus /prometheus && chmod g+w /prometheus + +USER nobody +EXPOSE 9090 +VOLUME [ "/prometheus" ] +ENTRYPOINT [ "/bin/prometheus" ] +CMD [ "--config.file=/etc/prometheus/prometheus.yml", \ + "--storage.tsdb.path=/prometheus" ] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Widoco/codemeta.json b/src/somef_core/test/test_data/repositories/Widoco/codemeta.json new file mode 100644 index 0000000..5f2d540 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/codemeta.json @@ -0,0 +1,62 @@ +{ + "@context": "https://w3id.org/codemeta/3.0", + "@type": "SoftwareSourceCode", + "license": { + "name": "Apache License 2.0", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE", + "identifier": "https://spdx.org/licenses/Apache-2.0" + }, + "codeRepository": "https://github.com/dgarijo/Widoco", + "issueTracker": "https://github.com/dgarijo/Widoco/issues", + "dateCreated": "2013-07-15", + "dateModified": "2025-01-31", + "downloadUrl": "https://github.com/dgarijo/Widoco/releases", + "name": "Widoco", + "logo": "https://raw.githubusercontent.com/dgarijo/Widoco/master/src/main/resources/logo/logo2.png", + "keywords": "documentation, metadata, ontology, ontology-diagram, ontology-evaluation, wizard", + "programmingLanguage": [ + "JavaScript", + "Java", + "XSLT", + "CSS", + "HTML", + "Dockerfile" + ], + "softwareRequirements": [ + "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.24\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n", + "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file.\n" + ], + "releaseNotes": "This version of WIDOCO fixes documentation broken links, clarifies how to download Docker images and includes a new option for excluding the provenance page from documentation (thanks to @MikiDi) \r\n\r\n## What's Changed\r\n* Bump docker/build-push-action from 5.3.0 to 5.4.0 by @dependabot in https://github.com/dgarijo/Widoco/pull/709\r\n* CLI option to exclude provenance link by @MikiDi in https://github.com/dgarijo/Widoco/pull/710\r\n* Improved documentation (broken links)\r\n\r\n\r\n**Full Changelog**: https://github.com/dgarijo/Widoco/compare/v1.4.24...v1.4.25", + "softwareVersion": "v1.4.25", + "buildInstructions": [ + "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + ], + "author": [ + { + "@type": "Person", + "@id": "http://orcid.org/0000-0003-0454-7145" + } + ], + "referencePublication": [ + { + "@type": "ScholarlyArticle", + "identifier": "10.1007/978-3-319-68204-4_9", + "author": { + "@type": "Person", + "givenName": "Daniel", + "familyName": "Garijo", + "@id": "http://orcid.org/0000-0003-0454-7145" + }, + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "name": "WIDOCO: a wizard for documenting ontologies", + "datePublished": "2017", + "pagination": "94--102" + } + ], + "identifier": "https://doi.org/10.5281/zenodo.11093793", + "readme": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md", + "description": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by María Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + ] + } \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.sml b/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.sml new file mode 100644 index 0000000..7839f52 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.sml @@ -0,0 +1,167 @@ + + 4.0.0 + es.oeg + widoco + jar + 1.4.26 + Widoco + + + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.apache.maven + maven-model + 3.9.0 + + + + org.jsoup + jsoup + 1.17.2 + + + com.github.VisualDataWeb + OWL2VOWL + 0.3.5 + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-simple + 1.7.30 + + + + + net.sf.saxon + Saxon-HE + 9.4 + + + + net.sourceforge.owlapi + owlapi-distribution + 5.1.18 + + + + com.googlecode.json-simple + json-simple + 1.1 + + + junit + junit + 4.13.1 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + ${project.artifactId}-${project.version}-jar-with-dependencies + true + launcher + JAR/ + + + widoco.gui.GuiController + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + 3.5.0 + true + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + + + + + + + + + + jitpack.io + https://jitpack.io + + + + unknown-jars-temp-repo + A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository. + file:${project.basedir}/lib + + + + + diff --git a/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.xml b/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.xml new file mode 100644 index 0000000..7839f52 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/docs/pom 2.xml @@ -0,0 +1,167 @@ + + 4.0.0 + es.oeg + widoco + jar + 1.4.26 + Widoco + + + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.apache.maven + maven-model + 3.9.0 + + + + org.jsoup + jsoup + 1.17.2 + + + com.github.VisualDataWeb + OWL2VOWL + 0.3.5 + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-simple + 1.7.30 + + + + + net.sf.saxon + Saxon-HE + 9.4 + + + + net.sourceforge.owlapi + owlapi-distribution + 5.1.18 + + + + com.googlecode.json-simple + json-simple + 1.1 + + + junit + junit + 4.13.1 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + ${project.artifactId}-${project.version}-jar-with-dependencies + true + launcher + JAR/ + + + widoco.gui.GuiController + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + 3.5.0 + true + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + + + + + + + + + + jitpack.io + https://jitpack.io + + + + unknown-jars-temp-repo + A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository. + file:${project.basedir}/lib + + + + + diff --git a/src/somef_core/test/test_data/repositories/Widoco/docs/pom.sml b/src/somef_core/test/test_data/repositories/Widoco/docs/pom.sml new file mode 100644 index 0000000..7839f52 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/docs/pom.sml @@ -0,0 +1,167 @@ + + 4.0.0 + es.oeg + widoco + jar + 1.4.26 + Widoco + + + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.apache.maven + maven-model + 3.9.0 + + + + org.jsoup + jsoup + 1.17.2 + + + com.github.VisualDataWeb + OWL2VOWL + 0.3.5 + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-simple + 1.7.30 + + + + + net.sf.saxon + Saxon-HE + 9.4 + + + + net.sourceforge.owlapi + owlapi-distribution + 5.1.18 + + + + com.googlecode.json-simple + json-simple + 1.1 + + + junit + junit + 4.13.1 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + ${project.artifactId}-${project.version}-jar-with-dependencies + true + launcher + JAR/ + + + widoco.gui.GuiController + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + 3.5.0 + true + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + + + + + + + + + + jitpack.io + https://jitpack.io + + + + unknown-jars-temp-repo + A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository. + file:${project.basedir}/lib + + + + + diff --git a/src/somef_core/test/test_data/repositories/Widoco/docs/pom.xml b/src/somef_core/test/test_data/repositories/Widoco/docs/pom.xml new file mode 100644 index 0000000..7839f52 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/docs/pom.xml @@ -0,0 +1,167 @@ + + 4.0.0 + es.oeg + widoco + jar + 1.4.26 + Widoco + + + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + org.apache.maven + maven-model + 3.9.0 + + + + org.jsoup + jsoup + 1.17.2 + + + com.github.VisualDataWeb + OWL2VOWL + 0.3.5 + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-simple + 1.7.30 + + + + + net.sf.saxon + Saxon-HE + 9.4 + + + + net.sourceforge.owlapi + owlapi-distribution + 5.1.18 + + + + com.googlecode.json-simple + json-simple + 1.1 + + + junit + junit + 4.13.1 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + ${project.artifactId}-${project.version}-jar-with-dependencies + true + launcher + JAR/ + + + widoco.gui.GuiController + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + org.apache.felix + maven-bundle-plugin + 3.5.0 + true + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + + + + + + + + + + jitpack.io + https://jitpack.io + + + + unknown-jars-temp-repo + A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository. + file:${project.basedir}/lib + + + + + diff --git a/src/somef_core/test/test_data/repositories/Widoco/example_onto/ontology.ttl b/src/somef_core/test/test_data/repositories/Widoco/example_onto/ontology.ttl new file mode 100644 index 0000000..70655c8 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/example_onto/ontology.ttl @@ -0,0 +1,159 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@base . + + rdf:type owl:Ontology ; + owl:versionIRI ; + "An example vocabulary designed to illustrate how to publish vocabularies on the Web following the FAIR principles"@en ; + "This is an example ontology to illustrate some of the annotations that should be included"@en ; + "The example ontology"@en ; + "February 5th, 2020"@en ; + "Daniel Garijo"@en , + "Maria Poveda-Villalon"@en ; + ; + "exo"@en ; + "https://w3id.org/example" ; + "Cite this vocabulary as: Garijo, D. and Poveda-Villalon, M. The example ontology 1.0.1."@en ; + rdfs:comment "An example vocabulary designed to illustrate how to publish vocabularies on the Web following the FAIR principles. This vocabulary describes three simple classes with 3 properties and a data property."@en ; + owl:backwardCompatibleWith ; + owl:priorVersion ; + owl:versionInfo "1.0.1"@en . + +################################################################# +# Annotation properties +################################################################# + +### http://purl.org/dc/elements/1.1/abstract + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/created + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/description + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/publisher + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/title + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/terms/created + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/terms/creator + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/terms/license + rdf:type owl:AnnotationProperty . + + +### http://purl.org/vocab/vann/example + rdf:type owl:AnnotationProperty . + + +### http://purl.org/vocab/vann/preferredNamespacePrefix + rdf:type owl:AnnotationProperty . + + +### http://purl.org/vocab/vann/preferredNamespaceUri + rdf:type owl:AnnotationProperty . + + +### http://schema.org/author + rdf:type owl:AnnotationProperty . + + +### http://schema.org/citation + rdf:type owl:AnnotationProperty . + + +### http://www.linkedmodel.org/schema/vaem#rationale + rdf:type owl:AnnotationProperty . + + +################################################################# +# Datatypes +################################################################# + +### http://www.w3.org/2001/XMLSchema#date +xsd:date rdf:type rdfs:Datatype . + + +################################################################# +# Object Properties +################################################################# + +### https://w3id.org/example#hasMember +:hasMember rdf:type owl:ObjectProperty ; + rdfs:domain :Organization ; + rdfs:range :Researcher ; + rdfs:comment "This example property indicates that an Organization has a Researcher as member"@en ; + rdfs:label "has member"@en . + + +### https://w3id.org/example#hasMentor +:hasMentor rdf:type owl:ObjectProperty ; + rdfs:domain :Student ; + rdfs:range :Researcher ; + rdfs:comment "This property links the students to the researcher who mentored them"@en ; + rdfs:label "has mentor"@en . + + +### https://w3id.org/example#partOf +:partOf rdf:type owl:ObjectProperty ; + rdfs:domain :Researcher ; + rdfs:range :Organization ; + rdfs:comment "This property links instances from Researcher to Organization"@en ; + rdfs:label "part of"@en . + + +################################################################# +# Data properties +################################################################# + +### https://w3id.org/example#foundedIn +:foundedIn rdf:type owl:DatatypeProperty ; + rdfs:domain :Organization ; + rdfs:range xsd:date ; + rdfs:comment "Date when an organization was founded"@en ; + rdfs:label "founded in"@en . + + +################################################################# +# Classes +################################################################# + +### https://w3id.org/example#Organization +:Organization rdf:type owl:Class ; + "University of Southern California"@en ; + rdfs:comment "An organized body of people with a particular purpose, especially a business, society, association, etc."@en ; + rdfs:label "Organization"@en . + + +### https://w3id.org/example#Researcher +:Researcher rdf:type owl:Class ; + "An example using the Researcher class, e.g., Bob is a professor at the University of Southern California."@en ; + "The reason why this concept was added to the ontology. This could reflect some agreement or use cases that may need to be reflected here. For example: The concept Researcher was added to the ontology to represent those authors of scientific publications that belong to a public institution."@en ; + rdfs:comment "A definition of your class. For example, A researcher is a person who publishes scientific papers, writes research proposals and mentors students"@en ; + rdfs:label "Researcher"@en . + + +### https://w3id.org/example#Student +:Student rdf:type owl:Class ; + rdfs:comment "Student is a class introduced in the version 1.0.1 of the ontology. "@en ; + rdfs:label "Student"@en . + + +### Generated by the OWL API (version 5.1.14) https://github.com/owlcs/owlapi/ diff --git a/src/somef_core/test/test_data/repositories/Widoco/example_onto/test.ttl b/src/somef_core/test/test_data/repositories/Widoco/example_onto/test.ttl new file mode 100644 index 0000000..e170e39 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/example_onto/test.ttl @@ -0,0 +1,9 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@base . + +:this a :Test . diff --git a/src/somef_core/test/test_data/repositories/Widoco/pom.xml b/src/somef_core/test/test_data/repositories/Widoco/pom.xml index 7839f52..6f9cdf1 100644 --- a/src/somef_core/test/test_data/repositories/Widoco/pom.xml +++ b/src/somef_core/test/test_data/repositories/Widoco/pom.xml @@ -163,5 +163,10 @@ - + + scm:svn:http://127.0.0.1/svn/my-project + scm:svn:https://127.0.0.1/svn/my-project + HEAD + http://127.0.0.1/websvn/my-project + diff --git a/src/somef_core/test/test_data/repositories/Widoco/target/maven-archiver/pom.properties b/src/somef_core/test/test_data/repositories/Widoco/target/maven-archiver/pom.properties new file mode 100644 index 0000000..5660eb4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/Widoco/target/maven-archiver/pom.properties @@ -0,0 +1,3 @@ +artifactId=widoco +groupId=es.oeg +version=1.4.26 diff --git a/src/somef_core/test/test_data/repositories/aladin-lite/codemeta.json b/src/somef_core/test/test_data/repositories/aladin-lite/codemeta.json new file mode 100644 index 0000000..6205dd2 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/aladin-lite/codemeta.json @@ -0,0 +1,83 @@ +{ + "@context": "https://doi.org/10.5063/schema/codemeta-2.0", + "@type": "SoftwareSourceCode", + "license": "https://spdx.org/licenses/GPL-3.0", + "codeRepository": "https://github.com/cds-astro/aladin-lite", + "dateCreated": "2013-05-01", + "datePublished": "2013-05-01", + "dateModified": "2023-01-31", + "issueTracker": "https://github.com/cds-astro/aladin-lite/issues", + "name": "Aladin Lite", + "version": "3.6.1", + "softwareVersion": "3.6.1", + "description": "An astronomical HiPS visualizer in the browser.", + "identifier": "10.5281/zenodo.7638833", + "applicationCategory": "Astronomy, Visualization", + "funding": "ESCAPE 824064", + "referencePublication": "http://aspbooks.org/publications/532/007.pdf", + "readme": "https://aladin.cds.unistra.fr/AladinLite/doc/", + "releaseNotes": "https://aladin.cds.unistra.fr/AladinLite/doc/#release-notes", + "funder": { + "@type": "Organization", + "name": "European Commission Framework Programme Horizon 2020 Research and Innovation action" + }, + "keywords": [ + "IVOA", + "Astronomy" + ], + "programmingLanguage": [ + "Rust", + "Javascript" + ], + "relatedLink": [ + "https://aladin.cds.unistra.fr/" + ], + "author": [ + { + "@type": "Person", + "@id": "https://orcid.org/0000-0002-7123-773X", + "givenName": "Matthieu", + "familyName": "Baumann", + "email": "matthieu.baumann@unistra.fr", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + } + }, + { + "@type": "Person", + "@id": "https://orcid.org/0000-0001-5818-2781", + "givenName": "Thomas", + "familyName": "Boch", + "email": "thomas.boch@astro.unistra.fr", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + } + } + ], + "maintainer": [ + { + "@type": "Person", + "@id": "https://orcid.org/0000-0002-7123-773X", + "givenName": "Matthieu", + "familyName": "Baumann", + "email": "matthieu.baumann@unistra.fr", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + } + }, + { + "@type": "Person", + "@id": "https://orcid.org/0000-0001-5818-2781", + "givenName": "Thomas", + "familyName": "Boch", + "email": "thomas.boch@astro.unistra.fr", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 de Strasbourg, CNRS, Observatoire astronomique de Strasbourg, UMR 7550, F-67000 Strasbourg, France" + } + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails 2.gemspec b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails 2.gemspec new file mode 100644 index 0000000..97a1db4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails 2.gemspec @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/bootstrap-datepicker-rails/version', __FILE__) + +Gem::Specification.new do |gem| + gem.authors = ["Gonzalo Rodríguez-Baltanás Díaz", "Author Dos"] + gem.email = ["siotopo@gmail.com"] + gem.description = %q{A date picker for Twitter Bootstrap} + gem.homepage = "https://github.com/Nerian/bootstrap-datepicker-rails" + gem.summary = gem.description + gem.license = 'MIT' + + gem.name = "bootstrap-datepicker-rails" + gem.require_paths = ["lib"] + gem.files = `git ls-files`.split("\n").reject { |i| i=~/testapp/} + gem.version = BootstrapDatepickerRails::Rails::VERSION + + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" + gem.add_development_dependency "rake" + gem.add_development_dependency "pry" + gem.add_development_dependency "json" +end \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2 2.gemspec b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2 2.gemspec new file mode 100644 index 0000000..88447b4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2 2.gemspec @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/bootstrap-datepicker-rails/version', __FILE__) + +Gem::Specification.new do |gem| + gem.author = "Gonzalo Rodríguez-Baltanás Díaz" + gem.email = ["siotopo@gmail.com"] + gem.description = %q{A date picker for Twitter Bootstrap} + gem.homepage = "https://github.com/Nerian/bootstrap-datepicker-rails" + gem.summary = gem.description + gem.license = 'MIT' + + gem.name = "bootstrap-datepicker-rails" + gem.require_paths = ["lib"] + gem.files = `git ls-files`.split("\n").reject { |i| i=~/testapp/} + gem.version = BootstrapDatepickerRails::Rails::VERSION + + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" + gem.add_development_dependency "rake" + gem.add_development_dependency "pry" + gem.add_development_dependency "json" +end \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2.gemspec b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2.gemspec new file mode 100644 index 0000000..88447b4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails-2.gemspec @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/bootstrap-datepicker-rails/version', __FILE__) + +Gem::Specification.new do |gem| + gem.author = "Gonzalo Rodríguez-Baltanás Díaz" + gem.email = ["siotopo@gmail.com"] + gem.description = %q{A date picker for Twitter Bootstrap} + gem.homepage = "https://github.com/Nerian/bootstrap-datepicker-rails" + gem.summary = gem.description + gem.license = 'MIT' + + gem.name = "bootstrap-datepicker-rails" + gem.require_paths = ["lib"] + gem.files = `git ls-files`.split("\n").reject { |i| i=~/testapp/} + gem.version = BootstrapDatepickerRails::Rails::VERSION + + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" + gem.add_development_dependency "rake" + gem.add_development_dependency "pry" + gem.add_development_dependency "json" +end \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails.gemspec b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails.gemspec new file mode 100644 index 0000000..97a1db4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/bootstrap-datepicker-rails/bootstrap-datepicker-rails.gemspec @@ -0,0 +1,22 @@ +# -*- encoding: utf-8 -*- +require File.expand_path('../lib/bootstrap-datepicker-rails/version', __FILE__) + +Gem::Specification.new do |gem| + gem.authors = ["Gonzalo Rodríguez-Baltanás Díaz", "Author Dos"] + gem.email = ["siotopo@gmail.com"] + gem.description = %q{A date picker for Twitter Bootstrap} + gem.homepage = "https://github.com/Nerian/bootstrap-datepicker-rails" + gem.summary = gem.description + gem.license = 'MIT' + + gem.name = "bootstrap-datepicker-rails" + gem.require_paths = ["lib"] + gem.files = `git ls-files`.split("\n").reject { |i| i=~/testapp/} + gem.version = BootstrapDatepickerRails::Rails::VERSION + + gem.add_dependency "railties", ">= 3.0" + gem.add_development_dependency "bundler", ">= 1.0" + gem.add_development_dependency "rake" + gem.add_development_dependency "pry" + gem.add_development_dependency "json" +end \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/chosen/bower.json b/src/somef_core/test/test_data/repositories/chosen/bower.json new file mode 100644 index 0000000..ed6bba3 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/chosen/bower.json @@ -0,0 +1,42 @@ +{ + "name": "chosen", + "description": "Chosen is a JavaScript plugin that makes select boxes user-friendly. It is currently available in both jQuery and Prototype flavors.", + "keywords": [ + "select", + "multiselect", + "dropdown", + "form", + "input", + "ui" + ], + "homepage": "https://harvesthq.github.io/chosen/", + "license": "https://github.com/harvesthq/chosen/blob/master/LICENSE.md", + "authors": [ + { + "name": "Patrick Filler", + "url": "https://github.com/pfiller" + }, + { + "name": "Christophe Coevoet", + "url": "https://github.com/stof" + }, + { + "name": "Ken Earley", + "url": "https://github.com/kenearley" + }, + { + "name": "Koen Punt", + "url": "https://github.com/koenpunt" + } + ], + "dependencies": {}, + "main": [ + "chosen.jquery.js", + "chosen.css" + ], + "ignore": [], + "repository": { + "type": "git", + "url": "https://github.com/harvesthq/chosen.git" + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/codecov/composer.json b/src/somef_core/test/test_data/repositories/codecov/composer.json new file mode 100644 index 0000000..ce8f5c0 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/codecov/composer.json @@ -0,0 +1,25 @@ +{ + "name": "codecov/codecov-php", + "type": "library", + "license": "MIT", + "homepage": "https://github.com/codecov/codecov-php", + "description": "Codecov Example PHP", + "keywords": ["code coverage", "codecov", "coverage reports"], + "authors": [ + { + "name": "codecov.io", + "email": "hello@codecov.io" + } + ], + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "~9.5" + }, + "autoload": { + "files": [ + "calculator/BasicCalculator.php" + ] + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/CITATION 2.cff b/src/somef_core/test/test_data/repositories/componentInstaller/CITATION 2.cff new file mode 100644 index 0000000..17f3ad6 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/CITATION 2.cff @@ -0,0 +1,23 @@ +cff-version: 1.2.0 +title: PySSA Component Installer +version: "1.0.0.0" +message: "If you use this software, please cite it as below." +type: software +authors: + - family-names: "Kullik" + given-names: "Hannah" + orcid: "https://orcid.org/0009-0004-5129-1298" + - family-names: "Urban" + given-names: "Martin" + orcid: "https://orcid.org/0009-0008-6834-5714" + - family-names: "Schaub" + given-names: "Jonas" + orcid: "https://orcid.org/0000-0003-1554-6666" + - family-names: "Loidl-Stahlhofen" + given-names: "Angelika" + orcid: "https://orcid.org/0000-0002-3158-9546" + - family-names: "Zielesny" + given-names: "Achim" + orcid: "https://orcid.org/0000-0003-0722-4229" +url: "https://github.com/urban233/ComponentInstaller" +license: "GPL-3.0" diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/CITATION.cff b/src/somef_core/test/test_data/repositories/componentInstaller/CITATION.cff new file mode 100644 index 0000000..17f3ad6 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/CITATION.cff @@ -0,0 +1,23 @@ +cff-version: 1.2.0 +title: PySSA Component Installer +version: "1.0.0.0" +message: "If you use this software, please cite it as below." +type: software +authors: + - family-names: "Kullik" + given-names: "Hannah" + orcid: "https://orcid.org/0009-0004-5129-1298" + - family-names: "Urban" + given-names: "Martin" + orcid: "https://orcid.org/0009-0008-6834-5714" + - family-names: "Schaub" + given-names: "Jonas" + orcid: "https://orcid.org/0000-0003-1554-6666" + - family-names: "Loidl-Stahlhofen" + given-names: "Angelika" + orcid: "https://orcid.org/0000-0002-3158-9546" + - family-names: "Zielesny" + given-names: "Achim" + orcid: "https://orcid.org/0000-0003-0722-4229" +url: "https://github.com/urban233/ComponentInstaller" +license: "GPL-3.0" diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE b/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE 2 b/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE 2 new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/LICENSE 2 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/README 2.md b/src/somef_core/test/test_data/repositories/componentInstaller/README 2.md new file mode 100644 index 0000000..75d1f1e --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/README 2.md @@ -0,0 +1,138 @@ +# Component Installer for deploying PySSA +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-blue.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/commit-activity) +[![GitHub issues](https://img.shields.io/github/issues/urban233/ComponentInstaller)](https://GitHub.com/urban233/ComponentInstaller/issues/) +[![GitHub contributors](https://img.shields.io/github/contributors/urban233/ComponentInstaller.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/contributors/) +[![GitHub release](https://img.shields.io/github/v/release/urban233/ComponentInstaller)](https://github.com/urban233/ComponentInstaller/releases/) + +## Contents of this document +* [Description](#Description) +* [Contents of this repository](#Contents-of-this-repository) + * [Sources](#Sources) + * [Documentation](#Documentation) + * [Assets](#Assets) +* [Build](#Build) + * [Windows](#Windows) + * [Source code](#Source-code) +* [Dependencies](#Dependencies) +* [Citation](#Citation) +* [References and useful links](#References-and-useful-links) +* [Acknowledgements](#Acknowledgements) + +## Description +The Component Installer is a software tool designed for use as a component-based installer. +It is capable of addressing a range of deployment contexts that typically necessitate more +intricate configuration than is typically required in other scenarios. +The PySSA Installer serves as a case study demonstrating +the potential utility of the component-based installation methodology. + + +## Contents of this repository +### Sources +The repository comprises four distinct source code units. + +- _src/main/java_ + - The package contains the communicator class, which is utilized for communication with WindowsTasks.exe. +- _src/main/kotlin_ + - The package contains the main source code, including gui and model. +- _WindowsWrapper/WindowsCmdElevator_ + - The package contains the class to elevate a normal cmd shell with admin privileges. +- _WindowsWrapper/WindowsTasks_ + - The package contains the communicator, which facilitates communication with the Kotlin application, as well as a number of useful classes for the management of the MS Windows operating system. + +### Documentation +The "deployment" folder +contains a user guide as PDF file. +This [PDF file](https://github.com/urban233/ComponentInstaller/blob/v1.0.1/deployment/inno_setup/PySSA-Component-Installer-User-Guide.pdf) is also available through the help menu item within the PySSA Component Installer. +The user guide explains the installation and uninstallation of every component +as well as the update procedure for ColabFold and PySSA. Furthermore, +it contains a troubleshooting section for WSL2 and ColabFold. + +### Assets +The "assets" folder contains +all logos including the WSL2, ColabFold and PySSA logo, as well as the PySSA Component Installer logo. +If you are using PySSA Component Installer for your own projects, you are welcome to give credit to PySSA Component Installer by using the logo in your presentations, etc. + +## Build +The Component Installer consists of a Kotlin/Java project and a C# solution with two projects. + +### Windows +To deploy the installer on a Microsoft Windows OS (10 or 11), use the provided +inno setup script as a starting point. +Be aware that the inno setup compiler needs to be pre-installed! + +### Source code +The Kotlin/Java project is a Gradle project. +In order to use the source code for your own software or do your own Component Installer build, +download or clone the repository and open it in a Gradle-supporting IDE (e.g. IntelliJ) +as a Gradle project and execute the build.gradle file. +Gradle will then take care of installing all dependencies. +A Java Development Kit (JDK) of version 17 must also be pre-installed and +set as project JDK / project compiler. + +The C# solution contains the C# project WindowsCmdElevator and WindowsTasks. Both can be compiled to +an .exe file using the provided FolderProfile.pubxml files. + +## Dependencies +**Needs to be pre-installed:** +* Java Development Kit (JDK) version 17 + * [Adoptium Open JDK](https://adoptium.net/temurin/archive/?version=17) (as one possible source of the JDK) +* .NET 8.0 + * [Microsoft .NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + +**Managed by Gradle:** +* Java Native Access (JNA) version 5.8.0 + * [Java Native Access GitHub repository](https://github.com/java-native-access) + * [LGPL, version 2.1 or later, or (from version 4.0 onward) the Apache License, version 2.0](https://github.com/java-native-access/jna?tab=License-1-ov-file) +* JeroMQ version 0.6.0 + * [JeroMQ GitHub repository](https://github.com/zeromq/jeromq) + * Mozilla Public License Version 2.0 + +**Managed by NuGet:** +* NLog version 5.3.2 + * [NLog GitHub repository](https://github.com/NLog/NLog) + * BSD-3-Clause license +* NetMQ version 4.0.1.13 + * [NetMQ GitHub repository](https://github.com/zeromq/netmq/) + * GNU Lesser General Public License 3 + +## Citation +You can cite this software or this repository as it is defined in the CITATION.cff file. + +## References and useful links +**Windows Subsystem for Linux** +* [What is the Windows Subsystem for Linux? (Article)](https://learn.microsoft.com/en-us/windows/wsl/about) +* [How to install Linux on Windows with WSL (Article)](https://learn.microsoft.com/en-us/windows/wsl/install) + +**ZeroMQ** +* [ZeroMQ Homepage](https://zeromq.org/) + * [Java implementation (JeroMQ)](https://github.com/zeromq/jeromq) + * [C# implementation (NetMQ)](https://github.com/zeromq/netmq/) + +## Acknowledgements +**Developers:** +* Martin Urban +* Hannah Kullik + +**End-user testers:** +* Jonas Schaub +* Achim Zielesny + +**Logo:** +* Martin Urban +* Hannah Kullik + +**Initialization, conceptualization, and supervision:** +* Achim Zielesny and Angelika Loidl-Stahlhofen + +**The ComponentInstaller project team would like to thank +the communities behind the open software libraries for their amazing work.** + + diff --git a/src/somef_core/test/test_data/repositories/componentInstaller/README.md b/src/somef_core/test/test_data/repositories/componentInstaller/README.md new file mode 100644 index 0000000..75d1f1e --- /dev/null +++ b/src/somef_core/test/test_data/repositories/componentInstaller/README.md @@ -0,0 +1,138 @@ +# Component Installer for deploying PySSA +[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) +[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-blue.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/commit-activity) +[![GitHub issues](https://img.shields.io/github/issues/urban233/ComponentInstaller)](https://GitHub.com/urban233/ComponentInstaller/issues/) +[![GitHub contributors](https://img.shields.io/github/contributors/urban233/ComponentInstaller.svg)](https://GitHub.com/urban233/ComponentInstaller/graphs/contributors/) +[![GitHub release](https://img.shields.io/github/v/release/urban233/ComponentInstaller)](https://github.com/urban233/ComponentInstaller/releases/) + +## Contents of this document +* [Description](#Description) +* [Contents of this repository](#Contents-of-this-repository) + * [Sources](#Sources) + * [Documentation](#Documentation) + * [Assets](#Assets) +* [Build](#Build) + * [Windows](#Windows) + * [Source code](#Source-code) +* [Dependencies](#Dependencies) +* [Citation](#Citation) +* [References and useful links](#References-and-useful-links) +* [Acknowledgements](#Acknowledgements) + +## Description +The Component Installer is a software tool designed for use as a component-based installer. +It is capable of addressing a range of deployment contexts that typically necessitate more +intricate configuration than is typically required in other scenarios. +The PySSA Installer serves as a case study demonstrating +the potential utility of the component-based installation methodology. + + +## Contents of this repository +### Sources +The repository comprises four distinct source code units. + +- _src/main/java_ + - The package contains the communicator class, which is utilized for communication with WindowsTasks.exe. +- _src/main/kotlin_ + - The package contains the main source code, including gui and model. +- _WindowsWrapper/WindowsCmdElevator_ + - The package contains the class to elevate a normal cmd shell with admin privileges. +- _WindowsWrapper/WindowsTasks_ + - The package contains the communicator, which facilitates communication with the Kotlin application, as well as a number of useful classes for the management of the MS Windows operating system. + +### Documentation +The "deployment" folder +contains a user guide as PDF file. +This [PDF file](https://github.com/urban233/ComponentInstaller/blob/v1.0.1/deployment/inno_setup/PySSA-Component-Installer-User-Guide.pdf) is also available through the help menu item within the PySSA Component Installer. +The user guide explains the installation and uninstallation of every component +as well as the update procedure for ColabFold and PySSA. Furthermore, +it contains a troubleshooting section for WSL2 and ColabFold. + +### Assets +The "assets" folder contains +all logos including the WSL2, ColabFold and PySSA logo, as well as the PySSA Component Installer logo. +If you are using PySSA Component Installer for your own projects, you are welcome to give credit to PySSA Component Installer by using the logo in your presentations, etc. + +## Build +The Component Installer consists of a Kotlin/Java project and a C# solution with two projects. + +### Windows +To deploy the installer on a Microsoft Windows OS (10 or 11), use the provided +inno setup script as a starting point. +Be aware that the inno setup compiler needs to be pre-installed! + +### Source code +The Kotlin/Java project is a Gradle project. +In order to use the source code for your own software or do your own Component Installer build, +download or clone the repository and open it in a Gradle-supporting IDE (e.g. IntelliJ) +as a Gradle project and execute the build.gradle file. +Gradle will then take care of installing all dependencies. +A Java Development Kit (JDK) of version 17 must also be pre-installed and +set as project JDK / project compiler. + +The C# solution contains the C# project WindowsCmdElevator and WindowsTasks. Both can be compiled to +an .exe file using the provided FolderProfile.pubxml files. + +## Dependencies +**Needs to be pre-installed:** +* Java Development Kit (JDK) version 17 + * [Adoptium Open JDK](https://adoptium.net/temurin/archive/?version=17) (as one possible source of the JDK) +* .NET 8.0 + * [Microsoft .NET 8.0](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) + +**Managed by Gradle:** +* Java Native Access (JNA) version 5.8.0 + * [Java Native Access GitHub repository](https://github.com/java-native-access) + * [LGPL, version 2.1 or later, or (from version 4.0 onward) the Apache License, version 2.0](https://github.com/java-native-access/jna?tab=License-1-ov-file) +* JeroMQ version 0.6.0 + * [JeroMQ GitHub repository](https://github.com/zeromq/jeromq) + * Mozilla Public License Version 2.0 + +**Managed by NuGet:** +* NLog version 5.3.2 + * [NLog GitHub repository](https://github.com/NLog/NLog) + * BSD-3-Clause license +* NetMQ version 4.0.1.13 + * [NetMQ GitHub repository](https://github.com/zeromq/netmq/) + * GNU Lesser General Public License 3 + +## Citation +You can cite this software or this repository as it is defined in the CITATION.cff file. + +## References and useful links +**Windows Subsystem for Linux** +* [What is the Windows Subsystem for Linux? (Article)](https://learn.microsoft.com/en-us/windows/wsl/about) +* [How to install Linux on Windows with WSL (Article)](https://learn.microsoft.com/en-us/windows/wsl/install) + +**ZeroMQ** +* [ZeroMQ Homepage](https://zeromq.org/) + * [Java implementation (JeroMQ)](https://github.com/zeromq/jeromq) + * [C# implementation (NetMQ)](https://github.com/zeromq/netmq/) + +## Acknowledgements +**Developers:** +* Martin Urban +* Hannah Kullik + +**End-user testers:** +* Jonas Schaub +* Achim Zielesny + +**Logo:** +* Martin Urban +* Hannah Kullik + +**Initialization, conceptualization, and supervision:** +* Achim Zielesny and Angelika Loidl-Stahlhofen + +**The ComponentInstaller project team would like to thank +the communities behind the open software libraries for their amazing work.** + + diff --git a/src/somef_core/test/test_data/repositories/composer/composer.json b/src/somef_core/test/test_data/repositories/composer/composer.json new file mode 100644 index 0000000..8e11d48 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/composer/composer.json @@ -0,0 +1,110 @@ +{ + "name": "composer/composer", + "type": "library", + "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.", + "keywords": [ + "package", + "dependency", + "autoload" + ], + "homepage": "https://getcomposer.org/", + "license": "MIT", + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "https://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "require": { + "php": "^7.2.5 || ^8.0", + "composer/ca-bundle": "^1.5", + "composer/class-map-generator": "^1.4.0", + "composer/metadata-minifier": "^1.0", + "composer/semver": "^3.3", + "composer/spdx-licenses": "^1.5.7", + "composer/xdebug-handler": "^2.0.2 || ^3.0.3", + "justinrainbow/json-schema": "^6.3.1", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "seld/jsonlint": "^1.4", + "seld/phar-utils": "^1.2", + "symfony/console": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/filesystem": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/finder": "^5.4.35 || ^6.3.12 || ^7.0.3", + "symfony/process": "^5.4.35 || ^6.3.12 || ^7.0.3", + "react/promise": "^2.11 || ^3.2", + "composer/pcre": "^2.2 || ^3.2", + "symfony/polyfill-php73": "^1.24", + "symfony/polyfill-php80": "^1.24", + "symfony/polyfill-php81": "^1.24", + "seld/signal-handler": "^2.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^6.4.3 || ^7.0.1", + "phpstan/phpstan": "^1.11.8", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-deprecation-rules": "^1.2.0", + "phpstan/phpstan-strict-rules": "^1.6.0", + "phpstan/phpstan-symfony": "^1.4.0" + }, + "suggest": { + "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages", + "ext-zip": "Enabling the zip extension allows you to unzip archives", + "ext-zlib": "Allow gzip compression of HTTP requests" + }, + "config": { + "platform": { + "php": "7.2.5" + }, + "platform-check": false + }, + "extra": { + "branch-alias": { + "dev-main": "2.9-dev" + }, + "phpstan": { + "includes": [ + "phpstan/rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Composer\\": "src/Composer/" + } + }, + "autoload-dev": { + "psr-4": { + "Composer\\Test\\": "tests/Composer/Test/" + }, + "exclude-from-classmap": [ + "tests/Composer/Test/Fixtures/", + "tests/Composer/Test/Autoload/Fixtures", + "tests/Composer/Test/Autoload/MinimumVersionSupport", + "tests/Composer/Test/Plugin/Fixtures" + ] + }, + "bin": [ + "bin/composer" + ], + "scripts": { + "compile": "@php -dphar.readonly=0 bin/compile", + "test": "@php simple-phpunit", + "phpstan": "@php vendor/bin/phpstan analyse --configuration=phpstan/config.neon" + }, + "scripts-descriptions": { + "compile": "Compile composer.phar", + "test": "Run all tests", + "phpstan": "Runs PHPStan" + }, + "support": { + "issues": "https://github.com/composer/composer/issues", + "irc": "ircs://irc.libera.chat:6697/composer", + "security": "https://github.com/composer/composer/security/policy" + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/AUTHORS b/src/somef_core/test/test_data/repositories/fuji/AUTHORS new file mode 100644 index 0000000..2154ae6 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/AUTHORS @@ -0,0 +1,19 @@ +# This is the list of F-ujis's contributors and their affiliation. +# To see the full list of contributors and their detailed contributions, +# see the revision history in source control + +Main authors: +Robert Huber (MARUM, rhuber@marum.de) +Anusuriya Devaraju (anusuriya.devaraju@googlemail.com) + + +We would also like to thank the following people for their contributions: + +Ahmad Z. Ihsan (HMC, FZJ, a.ihsan@fz-juelich.de) +Jens Bröder (HMC, FZJ, j.broeder@fz-juelich.de) +Pedro Videgain Barranco (HMC, FZJ, p.videgain.barranco@fz-juelich.de) +Steffen Neumann +Uwe Schindler (PANGAEA) +Vincent Emonet (vincent.emonet@gmail.com) +Wilko Steinhoff +Heinz-Alexander Fütterer \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/AUTHORS 2 b/src/somef_core/test/test_data/repositories/fuji/AUTHORS 2 new file mode 100644 index 0000000..2154ae6 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/AUTHORS 2 @@ -0,0 +1,19 @@ +# This is the list of F-ujis's contributors and their affiliation. +# To see the full list of contributors and their detailed contributions, +# see the revision history in source control + +Main authors: +Robert Huber (MARUM, rhuber@marum.de) +Anusuriya Devaraju (anusuriya.devaraju@googlemail.com) + + +We would also like to thank the following people for their contributions: + +Ahmad Z. Ihsan (HMC, FZJ, a.ihsan@fz-juelich.de) +Jens Bröder (HMC, FZJ, j.broeder@fz-juelich.de) +Pedro Videgain Barranco (HMC, FZJ, p.videgain.barranco@fz-juelich.de) +Steffen Neumann +Uwe Schindler (PANGAEA) +Vincent Emonet (vincent.emonet@gmail.com) +Wilko Steinhoff +Heinz-Alexander Fütterer \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/CITATION 2.cff b/src/somef_core/test/test_data/repositories/fuji/CITATION 2.cff new file mode 100644 index 0000000..347d94f --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/CITATION 2.cff @@ -0,0 +1,35 @@ +cff-version: 1.2.0 +title: F-UJI - An Automated FAIR Data Assessment Tool +message: Please cite this software using these metadata. +type: software +authors: + - given-names: Anusuriya + family-names: Devaraju + email: anusuriya.devaraju@googlemail.com + orcid: 'https://orcid.org/0000-0003-0870-3192' + - given-names: Robert + family-names: Huber + email: rhuber@marum.de + orcid: 'https://orcid.org/0000-0003-3000-0020' +identifiers: + - type: doi + value: 10.5281/zenodo.3934401 +repository-code: 'https://github.com/pangaea-data-publisher/fuji' +url: >- + https://www.fairsfair.eu/f-uji-automated-fair-data-assessment-tool +abstract: >- + FAIRsFAIR has developed F-UJI, a service based on + REST, and is piloting a programmatic assessment of + the FAIRness of research datasets in five + trustworthy data repositories. +keywords: + - PANGAEA + - FAIRsFAIR + - FAIR Principles + - Data Object Assessment + - OpenAPI + - FAIR + - Research Data + - FAIR data + - Metadata harvesting +license: MIT \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/CITATION.cff b/src/somef_core/test/test_data/repositories/fuji/CITATION.cff new file mode 100644 index 0000000..347d94f --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/CITATION.cff @@ -0,0 +1,35 @@ +cff-version: 1.2.0 +title: F-UJI - An Automated FAIR Data Assessment Tool +message: Please cite this software using these metadata. +type: software +authors: + - given-names: Anusuriya + family-names: Devaraju + email: anusuriya.devaraju@googlemail.com + orcid: 'https://orcid.org/0000-0003-0870-3192' + - given-names: Robert + family-names: Huber + email: rhuber@marum.de + orcid: 'https://orcid.org/0000-0003-3000-0020' +identifiers: + - type: doi + value: 10.5281/zenodo.3934401 +repository-code: 'https://github.com/pangaea-data-publisher/fuji' +url: >- + https://www.fairsfair.eu/f-uji-automated-fair-data-assessment-tool +abstract: >- + FAIRsFAIR has developed F-UJI, a service based on + REST, and is piloting a programmatic assessment of + the FAIRness of research datasets in five + trustworthy data repositories. +keywords: + - PANGAEA + - FAIRsFAIR + - FAIR Principles + - Data Object Assessment + - OpenAPI + - FAIR + - Research Data + - FAIR data + - Metadata harvesting +license: MIT \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/README 2.md b/src/somef_core/test/test_data/repositories/fuji/README 2.md new file mode 100644 index 0000000..7314311 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/README 2.md @@ -0,0 +1,265 @@ +# F-UJI (FAIRsFAIR Research Data Object Assessment Service) +Developers: [Robert Huber](mailto:rhuber@marum.de), [Anusuriya Devaraju](mailto:anusuriya.devaraju@googlemail.com) + +Thanks to [Heinz-Alexander Fuetterer](https://github.com/afuetterer) for his contributions and his help in cleaning up the code. + +[![CI](https://github.com/pangaea-data-publisher/fuji/actions/workflows/ci.yml/badge.svg)](https://github.com/pangaea-data-publisher/fuji/actions/workflows/ci.yml) +[![Coverage](https://pangaea-data-publisher.github.io/fuji/coverage/coveragebadge.svg)](https://pangaea-data-publisher.github.io/fuji/coverage/) + +[![Publish Docker image](https://github.com/pangaea-data-publisher/fuji/actions/workflows/publish-docker.yml/badge.svg)](https://github.com/pangaea-data-publisher/fuji/actions/workflows/publish-docker.yml) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11084909.svg)](https://doi.org/10.5281/zenodo.11084909) + +## Overview + +F-UJI is a web service to programmatically assess FAIRness of research data objects based on [metrics](https://doi.org/10.5281/zenodo.3775793) developed by the [FAIRsFAIR](https://www.fairsfair.eu/) project. +The service will be applied to demonstrate the evaluation of objects in repositories selected for in-depth collaboration with the project. + +The '__F__' stands for FAIR (of course) and '__UJI__' means 'Test' in Malay. So __F-UJI__ is a FAIR testing tool. + +**Cite as** + +Devaraju, A. and Huber, R. (2021). An automated solution for measuring the progress toward FAIR research data. Patterns, vol 2(11), https://doi.org/10.1016/j.patter.2021.100370 + +### Clients and User Interface + +A web demo using F-UJI is available at . + +An R client package that was generated from the F-UJI OpenAPI definition is available from . + +An open source web client for F-UJI is available at . + +## Assessment Scope, Constraint and Limitation +The service is **in development** and its assessment depends on several factors. +- In the FAIR ecosystem, FAIR assessment must go beyond the object itself. FAIR enabling services and repositories are vital to ensure that research data objects remain FAIR over time. Importantly, machine-readable services (e.g., registries) and documents (e.g., policies) are required to enable automated tests. +- In addition to repository and services requirements, automated testing depends on clear machine assessable criteria. Some aspects (rich, plurality, accurate, relevant) specified in FAIR principles still require human mediation and interpretation. +- The tests must focus on generally applicable data/metadata characteristics until domain/community-driven criteria have been agreed (e.g., appropriate schemas and required elements for usage/access control, etc.). For example, for some metrics (i.e., on I and R principles), the automated tests we proposed only inspect the ‘surface’ of criteria to be evaluated. Therefore, tests are designed in consideration of generic cross-domain metadata standards such as Dublin Core, DCAT, DataCite, schema.org, etc. +- FAIR assessment is performed based on aggregated metadata; this includes metadata embedded in the data (landing) page, metadata retrieved from a PID provider (e.g., DataCite content negotiation) and other services (e.g., re3data). + +![alt text](https://github.com/pangaea-data-publisher/fuji/blob/master/fuji_server/static/main.png?raw=true) + +## Requirements +[Python](https://www.python.org/downloads/) `3.11` + +### Google Dataset Search +* Download the latest Dataset Search corpus file from: +* Open file `fuji_server/helper/create_google_cache_db.py` and set variable 'google_file_location' according to the file location of the corpus file +* Run `create_google_cache_db.py` which creates a SQLite database in the data directory. From root directory run `python3 -m fuji_server.helper.create_google_cache_db`. + +The service was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. +The service uses the [Connexion](https://github.com/spec-first/connexion) library on top of Flask. + +## Usage +Before running the service, please set user details in the configuration file, see config/users.py. + +To install F-UJI, you may execute the following Python-based or docker-based installation commands from the root directory: + +### Python module-based installation + +From the fuji source folder run: +```bash +python -m pip install . +``` +The F-UJI server can now be started with: +```bash +python -m fuji_server -c fuji_server/config/server.ini +``` + +The OpenAPI user interface is then available at . + +### Docker-based installation + +```bash +docker run -d -p 1071:1071 ghcr.io/pangaea-data-publisher/fuji +``` + +To access the OpenAPI user interface, open the URL below in the browser: + + +Your OpenAPI definition lives here: + + + +You can provide a different server config file this way: + +```bash +docker run -d -p 1071:1071 -v server.ini:/usr/src/app/fuji_server/config/server.ini ghcr.io/pangaea-data-publisher/fuji +``` + +You can also build the docker image from the source code: + +```bash +docker build -t . +docker run -d -p 1071:1071 +``` + +### Notes + +To avoid Tika startup warning message, set environment variable `TIKA_LOG_PATH`. For more information, see [https://github.com/chrismattmann/tika-python](https://github.com/chrismattmann/tika-python) + +If you receive the exception `urllib2.URLError: , either by clicking on the link or through Settings -> Developer Settings -> Personal access tokens -> Tokens (classic). Next, click "Generate new token" and select "Generate new token (classic)" from the drop-down menu. + +Write the purpose of the token into the "Note" field (for example, *F-UJI deployment*) and set a suitable expiration date. Leave all the checkboxes underneath *unchecked*. + +> Note: When the token expires, you will receive an e-mail asking you to renew it if you still need it. The e-mail will provide a link to do so, and you will only need to change the token in the f-uji configuration as described below to continue using it. Setting no expiration date for a token is thus not recommended. + +When you click "Generate new token" at the bottom of the page, the new token will be displayed. Make a note of it now. + +To use F-UJI with a single access token, open [`fuji_server/config/github.ini`](./fuji_server/config/github.ini) locally and set `token` to the token you just created. When F-UJI receives an evaluation request that uses the GitHub API, it will run this request authenticated as your account. + +If you still run into rate limiting issues, you can use multiple GitHub API tokens. +These need to be generated by different GitHub accounts, as the rate limit applies to the user, not the token. +F-UJI will automatically switch to another token if the rate limit is near. +To do so, create a local file in [`fuji_server/data/`](./fuji_server/data/), called e.g. `github_api_tokens.txt`. Put all API tokens in that file, one token on each line. Then, open [`fuji_server/config/github.ini`](./fuji_server/config/github.ini) locally and set `token_file` to the absolute path to your local API token file. + +> Note: If you push a change containing a GitHub API token, GitHub will usually recognise this and invalidate the token immediately. You will need to regenerate the token. Please take care not to publish your API tokens anywhere. Even though they have very limited scope if you leave all the checkboxes unchecked during creation, they can allow someone else to run a request in your name. + +## Development + +First, make sure to read the [contribution guidelines](./CONTRIBUTING.md). +They include instructions on how to set up your environment with `pre-commit` and how to run the tests. + +The repository includes a [simple web client](./simpleclient/) suitable for interacting with the API during development. +One way to run it would be with a LEMP stack (Linux, Nginx, MySQL, PHP), which is described in the following. + +First, install the necessary packages: + +```bash +sudo apt-get update +sudo apt-get install nginx +sudo ufw allow 'Nginx HTTP' +sudo service mysql start # expects that mysql is already installed, if not run sudo apt install mysql-server +sudo service nginx start +sudo apt install php8.1-fpm php-mysql +sudo apt install php8.1-curl +sudo phpenmod curl +``` + +Next, configure the service by running `sudo vim /etc/nginx/sites-available/fuji-dev` and paste: + +```php +server { + listen 9000; + server_name fuji-dev; + root /var/www/fuji-dev; + + index index.php; + + location / { + try_files $uri $uri/ =404; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; + fastcgi_read_timeout 3600s; + } + + location ~ /\.ht { + deny all; + } +} +``` + +Link `simpleclient/index.php` and `simpleclient/icons/` to `/var/www/fuji-dev` by running `sudo ln /fuji/simpleclient/* /var/www/fuji-dev/`. You might need to adjust the file permissions to allow non-root writes. + +Next, +```bash +sudo ln -s /etc/nginx/sites-available/fuji-dev /etc/nginx/sites-enabled/ +sudo nginx -t +sudo service nginx reload +sudo service php8.1-fpm start +``` + +The web client should now be available at . Make sure to adjust the username and password in [`simpleclient/index.php`](./simpleclient/index.php). + +After a restart, it may be necessary to start the services again: + +```bash +sudo service php8.1-fpm start +sudo service nginx start +python -m fuji_server -c fuji_server/config/server.ini +``` + +### Component interaction (walkthrough) + +This walkthrough can guide you through the comprehensive codebase. + +A good starting point is [`fair_object_controller/assess_by_id`](fuji_server/controllers/fair_object_controller.py#36). +Here, we create a [`FAIRCheck`](fuji_server/controllers/fair_check.py) object called `ft`. +This reads the metrics YAML file during initialisation and will provide all the `check` methods. + +Next, several harvesting methods are called, first [`harvest_all_metadata`](fuji_server/controllers/fair_check.py#329), followed by [`harvest_re3_data`](fuji_server/controllers/fair_check.py#345) (Datacite) and [`harvest_github`](fuji_server/controllers/fair_check.py#366) and finally [`harvest_all_data`](fuji_server/controllers/fair_check.py#359). +The harvesters are implemented separately in [`harvester/`](./fuji_server/harvester/), and each of them collects different kinds of data. +This is regardless of the defined metrics, the harvesters always run. +- The metadata harvester looks through HTML markup following schema.org, Dublincore etc., through signposting/typed links. +Ideally, it can find things like author information or license names that way. +- The data harvester is only run if the metadata harvester finds an `object_content_identifier` pointing at content files. +Then, the data harvester runs over the files and checks things like the file format. +- The Github harvester connects with the GitHub API to retrieve metadata and data from software repositories. +It relies on an access token being defined in [`config/github.cfg`](./fujji_server/config/github.cfg). + +After harvesting, all evaluators are called. +Each specific evaluator, e.g. [`FAIREvaluatorLicense`](fuji_server/evaluators/fair_evaluator_license.py), is associated with a specific FsF and/or FAIR4RS metric. +Before the evaluator runs any checks on the harvested data, it asserts that its associated metric is listed in the metrics YAML file. +Only if it is, the evaluator runs through and computes a local score. + +In the end, all scores are aggregated into F, A, I, R scores. + +### Adding support for new metrics + +Start by adding a new metrics YAML file in [`yaml/`](./fuji_server/yaml). +Its name has to match the following regular expression: `(metrics_v)?([0-9]+\.[0-9]+)(_[a-z]+)?(\.yaml)`, +and the content should be structured similarly to the existing metric files. + +Metric names are tested for validity using regular expressions throughout the code. +If your metric names do not match those, not all components of the tool will execute as expected, so make sure to adjust the expressions. +Regular expression groups are also used for mapping to F, A, I, R categories for scoring, and debug messages are only displayed if they are associated with a valid metric. + +Evaluators are mapped to metrics in their `__init__` methods, so adjust existing evaluators to associate with your metric as well or define new evaluators if needed. +The multiple test methods within an evaluator also check whether their specific test is defined. +[`FAIREvaluatorLicense`](fuji_server/evaluators/fair_evaluator_license.py) is an example of an evaluator corresponding to metrics from different sources. + +For each metric, the maturity is determined as the maximum of the maturity associated with each passed test. +This means that if a test indicating maturity 3 is passed and one indicating maturity 2 is not passed, the metric will still be shown to be fulfilled with maturity 3. + +### Community specific metrics + +Some, not all, metrics can be configured using the following guidelines: +[Metrics configuration guide](https://github.com/pangaea-data-publisher/fuji/blob/master/metrics_configuration.md) + +### Updates to the API + +Making changes to the API requires re-generating parts of the code using Swagger. +First, edit [`fuji_server/yaml/openapi.yaml`](fuji_server/yaml/openapi.yaml). +Then, use the [Swagger Editor](https://editor.swagger.io/) to generate a python-flask server. +The zipped files should be automatically downloaded. +Unzip it. + +Next: +1. Place the files in `swagger_server/models` into `fuji_server/models`, except `swagger_server/models/__init__.py`. +2. Rename all occurrences of `swagger_server` to `fuji_server`. +3. Add the content of `swagger_server/models/__init__.py` into `fuji_server/__init__.py`. + +Unfortunately, the Swagger Editor doesn't always produce code that is compliant with PEP standards. +Run `pre-commit run` (or try to commit) and fix any errors that cannot be automatically fixed. + +## License +This project is licensed under the MIT License; for more details, see the [LICENSE](https://github.com/pangaea-data-publisher/fuji/blob/master/LICENSE) file. + + +## Acknowledgements + +F-UJI is a result of the [FAIRsFAIR](https://www.fairsfair.eu/) “Fostering FAIR Data Practices In Europe” project which received funding from the European Union’s Horizon 2020 project call H2020-INFRAEOSC-2018-2020 (grant agreement 831558). + +The project was also supported through our contributors by the [Helmholtz Metadata Collaboration (HMC)](https://www.helmholtz-metadaten.de/en), an incubator-platform of the Helmholtz Association within the framework of the Information and Data Science strategic initiative. \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/README.md b/src/somef_core/test/test_data/repositories/fuji/README.md new file mode 100644 index 0000000..7314311 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/README.md @@ -0,0 +1,265 @@ +# F-UJI (FAIRsFAIR Research Data Object Assessment Service) +Developers: [Robert Huber](mailto:rhuber@marum.de), [Anusuriya Devaraju](mailto:anusuriya.devaraju@googlemail.com) + +Thanks to [Heinz-Alexander Fuetterer](https://github.com/afuetterer) for his contributions and his help in cleaning up the code. + +[![CI](https://github.com/pangaea-data-publisher/fuji/actions/workflows/ci.yml/badge.svg)](https://github.com/pangaea-data-publisher/fuji/actions/workflows/ci.yml) +[![Coverage](https://pangaea-data-publisher.github.io/fuji/coverage/coveragebadge.svg)](https://pangaea-data-publisher.github.io/fuji/coverage/) + +[![Publish Docker image](https://github.com/pangaea-data-publisher/fuji/actions/workflows/publish-docker.yml/badge.svg)](https://github.com/pangaea-data-publisher/fuji/actions/workflows/publish-docker.yml) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11084909.svg)](https://doi.org/10.5281/zenodo.11084909) + +## Overview + +F-UJI is a web service to programmatically assess FAIRness of research data objects based on [metrics](https://doi.org/10.5281/zenodo.3775793) developed by the [FAIRsFAIR](https://www.fairsfair.eu/) project. +The service will be applied to demonstrate the evaluation of objects in repositories selected for in-depth collaboration with the project. + +The '__F__' stands for FAIR (of course) and '__UJI__' means 'Test' in Malay. So __F-UJI__ is a FAIR testing tool. + +**Cite as** + +Devaraju, A. and Huber, R. (2021). An automated solution for measuring the progress toward FAIR research data. Patterns, vol 2(11), https://doi.org/10.1016/j.patter.2021.100370 + +### Clients and User Interface + +A web demo using F-UJI is available at . + +An R client package that was generated from the F-UJI OpenAPI definition is available from . + +An open source web client for F-UJI is available at . + +## Assessment Scope, Constraint and Limitation +The service is **in development** and its assessment depends on several factors. +- In the FAIR ecosystem, FAIR assessment must go beyond the object itself. FAIR enabling services and repositories are vital to ensure that research data objects remain FAIR over time. Importantly, machine-readable services (e.g., registries) and documents (e.g., policies) are required to enable automated tests. +- In addition to repository and services requirements, automated testing depends on clear machine assessable criteria. Some aspects (rich, plurality, accurate, relevant) specified in FAIR principles still require human mediation and interpretation. +- The tests must focus on generally applicable data/metadata characteristics until domain/community-driven criteria have been agreed (e.g., appropriate schemas and required elements for usage/access control, etc.). For example, for some metrics (i.e., on I and R principles), the automated tests we proposed only inspect the ‘surface’ of criteria to be evaluated. Therefore, tests are designed in consideration of generic cross-domain metadata standards such as Dublin Core, DCAT, DataCite, schema.org, etc. +- FAIR assessment is performed based on aggregated metadata; this includes metadata embedded in the data (landing) page, metadata retrieved from a PID provider (e.g., DataCite content negotiation) and other services (e.g., re3data). + +![alt text](https://github.com/pangaea-data-publisher/fuji/blob/master/fuji_server/static/main.png?raw=true) + +## Requirements +[Python](https://www.python.org/downloads/) `3.11` + +### Google Dataset Search +* Download the latest Dataset Search corpus file from: +* Open file `fuji_server/helper/create_google_cache_db.py` and set variable 'google_file_location' according to the file location of the corpus file +* Run `create_google_cache_db.py` which creates a SQLite database in the data directory. From root directory run `python3 -m fuji_server.helper.create_google_cache_db`. + +The service was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[OpenAPI-Spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. +The service uses the [Connexion](https://github.com/spec-first/connexion) library on top of Flask. + +## Usage +Before running the service, please set user details in the configuration file, see config/users.py. + +To install F-UJI, you may execute the following Python-based or docker-based installation commands from the root directory: + +### Python module-based installation + +From the fuji source folder run: +```bash +python -m pip install . +``` +The F-UJI server can now be started with: +```bash +python -m fuji_server -c fuji_server/config/server.ini +``` + +The OpenAPI user interface is then available at . + +### Docker-based installation + +```bash +docker run -d -p 1071:1071 ghcr.io/pangaea-data-publisher/fuji +``` + +To access the OpenAPI user interface, open the URL below in the browser: + + +Your OpenAPI definition lives here: + + + +You can provide a different server config file this way: + +```bash +docker run -d -p 1071:1071 -v server.ini:/usr/src/app/fuji_server/config/server.ini ghcr.io/pangaea-data-publisher/fuji +``` + +You can also build the docker image from the source code: + +```bash +docker build -t . +docker run -d -p 1071:1071 +``` + +### Notes + +To avoid Tika startup warning message, set environment variable `TIKA_LOG_PATH`. For more information, see [https://github.com/chrismattmann/tika-python](https://github.com/chrismattmann/tika-python) + +If you receive the exception `urllib2.URLError: , either by clicking on the link or through Settings -> Developer Settings -> Personal access tokens -> Tokens (classic). Next, click "Generate new token" and select "Generate new token (classic)" from the drop-down menu. + +Write the purpose of the token into the "Note" field (for example, *F-UJI deployment*) and set a suitable expiration date. Leave all the checkboxes underneath *unchecked*. + +> Note: When the token expires, you will receive an e-mail asking you to renew it if you still need it. The e-mail will provide a link to do so, and you will only need to change the token in the f-uji configuration as described below to continue using it. Setting no expiration date for a token is thus not recommended. + +When you click "Generate new token" at the bottom of the page, the new token will be displayed. Make a note of it now. + +To use F-UJI with a single access token, open [`fuji_server/config/github.ini`](./fuji_server/config/github.ini) locally and set `token` to the token you just created. When F-UJI receives an evaluation request that uses the GitHub API, it will run this request authenticated as your account. + +If you still run into rate limiting issues, you can use multiple GitHub API tokens. +These need to be generated by different GitHub accounts, as the rate limit applies to the user, not the token. +F-UJI will automatically switch to another token if the rate limit is near. +To do so, create a local file in [`fuji_server/data/`](./fuji_server/data/), called e.g. `github_api_tokens.txt`. Put all API tokens in that file, one token on each line. Then, open [`fuji_server/config/github.ini`](./fuji_server/config/github.ini) locally and set `token_file` to the absolute path to your local API token file. + +> Note: If you push a change containing a GitHub API token, GitHub will usually recognise this and invalidate the token immediately. You will need to regenerate the token. Please take care not to publish your API tokens anywhere. Even though they have very limited scope if you leave all the checkboxes unchecked during creation, they can allow someone else to run a request in your name. + +## Development + +First, make sure to read the [contribution guidelines](./CONTRIBUTING.md). +They include instructions on how to set up your environment with `pre-commit` and how to run the tests. + +The repository includes a [simple web client](./simpleclient/) suitable for interacting with the API during development. +One way to run it would be with a LEMP stack (Linux, Nginx, MySQL, PHP), which is described in the following. + +First, install the necessary packages: + +```bash +sudo apt-get update +sudo apt-get install nginx +sudo ufw allow 'Nginx HTTP' +sudo service mysql start # expects that mysql is already installed, if not run sudo apt install mysql-server +sudo service nginx start +sudo apt install php8.1-fpm php-mysql +sudo apt install php8.1-curl +sudo phpenmod curl +``` + +Next, configure the service by running `sudo vim /etc/nginx/sites-available/fuji-dev` and paste: + +```php +server { + listen 9000; + server_name fuji-dev; + root /var/www/fuji-dev; + + index index.php; + + location / { + try_files $uri $uri/ =404; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; + fastcgi_read_timeout 3600s; + } + + location ~ /\.ht { + deny all; + } +} +``` + +Link `simpleclient/index.php` and `simpleclient/icons/` to `/var/www/fuji-dev` by running `sudo ln /fuji/simpleclient/* /var/www/fuji-dev/`. You might need to adjust the file permissions to allow non-root writes. + +Next, +```bash +sudo ln -s /etc/nginx/sites-available/fuji-dev /etc/nginx/sites-enabled/ +sudo nginx -t +sudo service nginx reload +sudo service php8.1-fpm start +``` + +The web client should now be available at . Make sure to adjust the username and password in [`simpleclient/index.php`](./simpleclient/index.php). + +After a restart, it may be necessary to start the services again: + +```bash +sudo service php8.1-fpm start +sudo service nginx start +python -m fuji_server -c fuji_server/config/server.ini +``` + +### Component interaction (walkthrough) + +This walkthrough can guide you through the comprehensive codebase. + +A good starting point is [`fair_object_controller/assess_by_id`](fuji_server/controllers/fair_object_controller.py#36). +Here, we create a [`FAIRCheck`](fuji_server/controllers/fair_check.py) object called `ft`. +This reads the metrics YAML file during initialisation and will provide all the `check` methods. + +Next, several harvesting methods are called, first [`harvest_all_metadata`](fuji_server/controllers/fair_check.py#329), followed by [`harvest_re3_data`](fuji_server/controllers/fair_check.py#345) (Datacite) and [`harvest_github`](fuji_server/controllers/fair_check.py#366) and finally [`harvest_all_data`](fuji_server/controllers/fair_check.py#359). +The harvesters are implemented separately in [`harvester/`](./fuji_server/harvester/), and each of them collects different kinds of data. +This is regardless of the defined metrics, the harvesters always run. +- The metadata harvester looks through HTML markup following schema.org, Dublincore etc., through signposting/typed links. +Ideally, it can find things like author information or license names that way. +- The data harvester is only run if the metadata harvester finds an `object_content_identifier` pointing at content files. +Then, the data harvester runs over the files and checks things like the file format. +- The Github harvester connects with the GitHub API to retrieve metadata and data from software repositories. +It relies on an access token being defined in [`config/github.cfg`](./fujji_server/config/github.cfg). + +After harvesting, all evaluators are called. +Each specific evaluator, e.g. [`FAIREvaluatorLicense`](fuji_server/evaluators/fair_evaluator_license.py), is associated with a specific FsF and/or FAIR4RS metric. +Before the evaluator runs any checks on the harvested data, it asserts that its associated metric is listed in the metrics YAML file. +Only if it is, the evaluator runs through and computes a local score. + +In the end, all scores are aggregated into F, A, I, R scores. + +### Adding support for new metrics + +Start by adding a new metrics YAML file in [`yaml/`](./fuji_server/yaml). +Its name has to match the following regular expression: `(metrics_v)?([0-9]+\.[0-9]+)(_[a-z]+)?(\.yaml)`, +and the content should be structured similarly to the existing metric files. + +Metric names are tested for validity using regular expressions throughout the code. +If your metric names do not match those, not all components of the tool will execute as expected, so make sure to adjust the expressions. +Regular expression groups are also used for mapping to F, A, I, R categories for scoring, and debug messages are only displayed if they are associated with a valid metric. + +Evaluators are mapped to metrics in their `__init__` methods, so adjust existing evaluators to associate with your metric as well or define new evaluators if needed. +The multiple test methods within an evaluator also check whether their specific test is defined. +[`FAIREvaluatorLicense`](fuji_server/evaluators/fair_evaluator_license.py) is an example of an evaluator corresponding to metrics from different sources. + +For each metric, the maturity is determined as the maximum of the maturity associated with each passed test. +This means that if a test indicating maturity 3 is passed and one indicating maturity 2 is not passed, the metric will still be shown to be fulfilled with maturity 3. + +### Community specific metrics + +Some, not all, metrics can be configured using the following guidelines: +[Metrics configuration guide](https://github.com/pangaea-data-publisher/fuji/blob/master/metrics_configuration.md) + +### Updates to the API + +Making changes to the API requires re-generating parts of the code using Swagger. +First, edit [`fuji_server/yaml/openapi.yaml`](fuji_server/yaml/openapi.yaml). +Then, use the [Swagger Editor](https://editor.swagger.io/) to generate a python-flask server. +The zipped files should be automatically downloaded. +Unzip it. + +Next: +1. Place the files in `swagger_server/models` into `fuji_server/models`, except `swagger_server/models/__init__.py`. +2. Rename all occurrences of `swagger_server` to `fuji_server`. +3. Add the content of `swagger_server/models/__init__.py` into `fuji_server/__init__.py`. + +Unfortunately, the Swagger Editor doesn't always produce code that is compliant with PEP standards. +Run `pre-commit run` (or try to commit) and fix any errors that cannot be automatically fixed. + +## License +This project is licensed under the MIT License; for more details, see the [LICENSE](https://github.com/pangaea-data-publisher/fuji/blob/master/LICENSE) file. + + +## Acknowledgements + +F-UJI is a result of the [FAIRsFAIR](https://www.fairsfair.eu/) “Fostering FAIR Data Practices In Europe” project which received funding from the European Union’s Horizon 2020 project call H2020-INFRAEOSC-2018-2020 (grant agreement 831558). + +The project was also supported through our contributors by the [Helmholtz Metadata Collaboration (HMC)](https://www.helmholtz-metadaten.de/en), an incubator-platform of the Helmholtz Association within the framework of the Information and Data Science strategic initiative. \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/pyproject 2.toml b/src/somef_core/test/test_data/repositories/fuji/pyproject 2.toml new file mode 100644 index 0000000..a5dd2db --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/pyproject 2.toml @@ -0,0 +1,169 @@ +[build-system] +build-backend = "hatchling.build" +requires = ["hatchling"] + +[project] +authors = [ + {name = "Robert Huber", email = "rhuber@marum.de"}, + {name = "Anusuriya Devaraju", email = "anusuriya.devaraju@googlemail.com"} +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.11", + "Topic :: Scientific/Engineering :: Information Analysis" +] +dependencies = [ + # dependencies with major version on zero are defined with + # major.minor.patch, because they can potentially introduce breaking changes + # in minor version updates anytime + "beautifulsoup4~=4.12", + "configparser~=6.0", + "connexion[flask,uvicorn,swagger-ui]~=3.0", + "extruct~=0.16.0", + "feedparser~=6.0", + "flask-cors~=4.0", + "flask-limiter~=3.5", + "hashid~=3.1.4", + "idutils~=1.2", + "jmespath~=1.0", + "levenshtein~=0.25.0", + "lxml==5.1.0", + "pandas~=2.1", + "pyRdfa3~=3.5", + "pyld~=2.0", + "pyyaml~=6.0", + "rapidfuzz~=3.3", + "rdflib~=7.0", + "requests~=2.31", + "sparqlwrapper~=2.0", + "tika~=2.6", + "tldextract~=5.0", + "urlextract~=1.8", + "pygithub~=2.1" +] +description = "FUJI (FAIRsFAIR Data Objects Assessment Service), A service to evaluate FAIR data objects based on FAIRsFAIR Metrics" +keywords = [ + "PANGAEA", + "FAIRsFAIR", + "FAIR Principles", + "Data Object Assessment", + "OpenAPI", + "FAIR", + "Research Data", + "FAIR data", + "Metadata harvesting", + "FAIR4RS" +] +license = "MIT" +name = "fuji" +readme = "README.md" +requires-python = "~=3.11" # at the moment only Python 3.11 is supported +version = "3.2.0" + +[project.optional-dependencies] +dev = [ + "fuji[lint]", + "fuji[testing]" +] +docs = [ + "myst-parser~=2.0", + "sphinx~=7.2", + "sphinx-rtd-theme~=2.0" +] +lint = [ + "pre-commit~=3.4" +] +report = [ + "bokeh~=3.2", + "jupyter~=1.0" +] +testing = [ + "genbadge[coverage]~=1.1", + "pytest~=8.0", + "pytest-cov~=5.0", + "pytest-randomly~=3.15", + "pytest-recording~=0.13", + "pytest-xdist~=3.3" +] + +[project.urls] +Homepage = "https://www.f-uji.net" +Issues = "https://github.com/pangaea-data-publisher/fuji/issues" +Source = "https://github.com/pangaea-data-publisher/fuji" + +[tool.coverage.report] +show_missing = true +skip_covered = true +skip_empty = true + +[tool.coverage.run] +branch = true +parallel = true +source = ["fuji_server"] + +[tool.hatch.build] +include = [ + "docs", + "fuji_server", + "AUTHORS", + "LICENSE", + "README.md" +] + +[tool.hatch.build.targets.wheel] +packages = ["fuji_server"] + +[tool.hatch.envs.default] +dev-mode = true +features = [ + "lint", + "testing" +] + +[tool.hatch.envs.default.scripts] +cov = "pytest --cov {args}" +cov-badge = "genbadge coverage --input-file=pytest-cobertura.xml --output-file=./reports/coverage/coveragebadge.svg" +cov-ci = "pytest --cov --junitxml=pytest-junit.xml --cov-report=xml:pytest-cobertura.xml --cov-report=html:./reports/coverage/ {args}" +lint = "pre-commit run --all-files --color=always {args}" +test = "pytest {args}" + +[tool.pytest.ini_options] +filterwarnings = [ + # warnings from pyrdfa + "ignore: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12:DeprecationWarning", + # warnings from feedparser + "ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning", + # warnings from tika + "ignore:pkg_resources is deprecated as an API:DeprecationWarning", + "ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning" +] +markers = [ + "manual", # tests which should be triggered manual only + "noci", # tests which should not run on the CI + "regression", # tests which run a fuji as a whole + "smoke" # tests which run very fast +] +testpaths = "tests" + +[tool.ruff] +line-length = 120 +# Ref: https://docs.astral.sh/ruff/configuration/ +src = ["fuji_server"] +target-version = "py311" + +[tool.ruff.lint] +extend-select = [ + "I", # isort + "UP", # pyupgrade + "RUF" # ruff +] +ignore = [ + "E722", # bare-except + "RUF012" # mutable-class-default +] + +[tool.ruff.lint.isort] +known-first-party = ["fuji_server", "tests"] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/fuji/pyproject.toml b/src/somef_core/test/test_data/repositories/fuji/pyproject.toml new file mode 100644 index 0000000..a5dd2db --- /dev/null +++ b/src/somef_core/test/test_data/repositories/fuji/pyproject.toml @@ -0,0 +1,169 @@ +[build-system] +build-backend = "hatchling.build" +requires = ["hatchling"] + +[project] +authors = [ + {name = "Robert Huber", email = "rhuber@marum.de"}, + {name = "Anusuriya Devaraju", email = "anusuriya.devaraju@googlemail.com"} +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.11", + "Topic :: Scientific/Engineering :: Information Analysis" +] +dependencies = [ + # dependencies with major version on zero are defined with + # major.minor.patch, because they can potentially introduce breaking changes + # in minor version updates anytime + "beautifulsoup4~=4.12", + "configparser~=6.0", + "connexion[flask,uvicorn,swagger-ui]~=3.0", + "extruct~=0.16.0", + "feedparser~=6.0", + "flask-cors~=4.0", + "flask-limiter~=3.5", + "hashid~=3.1.4", + "idutils~=1.2", + "jmespath~=1.0", + "levenshtein~=0.25.0", + "lxml==5.1.0", + "pandas~=2.1", + "pyRdfa3~=3.5", + "pyld~=2.0", + "pyyaml~=6.0", + "rapidfuzz~=3.3", + "rdflib~=7.0", + "requests~=2.31", + "sparqlwrapper~=2.0", + "tika~=2.6", + "tldextract~=5.0", + "urlextract~=1.8", + "pygithub~=2.1" +] +description = "FUJI (FAIRsFAIR Data Objects Assessment Service), A service to evaluate FAIR data objects based on FAIRsFAIR Metrics" +keywords = [ + "PANGAEA", + "FAIRsFAIR", + "FAIR Principles", + "Data Object Assessment", + "OpenAPI", + "FAIR", + "Research Data", + "FAIR data", + "Metadata harvesting", + "FAIR4RS" +] +license = "MIT" +name = "fuji" +readme = "README.md" +requires-python = "~=3.11" # at the moment only Python 3.11 is supported +version = "3.2.0" + +[project.optional-dependencies] +dev = [ + "fuji[lint]", + "fuji[testing]" +] +docs = [ + "myst-parser~=2.0", + "sphinx~=7.2", + "sphinx-rtd-theme~=2.0" +] +lint = [ + "pre-commit~=3.4" +] +report = [ + "bokeh~=3.2", + "jupyter~=1.0" +] +testing = [ + "genbadge[coverage]~=1.1", + "pytest~=8.0", + "pytest-cov~=5.0", + "pytest-randomly~=3.15", + "pytest-recording~=0.13", + "pytest-xdist~=3.3" +] + +[project.urls] +Homepage = "https://www.f-uji.net" +Issues = "https://github.com/pangaea-data-publisher/fuji/issues" +Source = "https://github.com/pangaea-data-publisher/fuji" + +[tool.coverage.report] +show_missing = true +skip_covered = true +skip_empty = true + +[tool.coverage.run] +branch = true +parallel = true +source = ["fuji_server"] + +[tool.hatch.build] +include = [ + "docs", + "fuji_server", + "AUTHORS", + "LICENSE", + "README.md" +] + +[tool.hatch.build.targets.wheel] +packages = ["fuji_server"] + +[tool.hatch.envs.default] +dev-mode = true +features = [ + "lint", + "testing" +] + +[tool.hatch.envs.default.scripts] +cov = "pytest --cov {args}" +cov-badge = "genbadge coverage --input-file=pytest-cobertura.xml --output-file=./reports/coverage/coveragebadge.svg" +cov-ci = "pytest --cov --junitxml=pytest-junit.xml --cov-report=xml:pytest-cobertura.xml --cov-report=html:./reports/coverage/ {args}" +lint = "pre-commit run --all-files --color=always {args}" +test = "pytest {args}" + +[tool.pytest.ini_options] +filterwarnings = [ + # warnings from pyrdfa + "ignore: the imp module is deprecated in favour of importlib and slated for removal in Python 3.12:DeprecationWarning", + # warnings from feedparser + "ignore:'cgi' is deprecated and slated for removal in Python 3.13:DeprecationWarning", + # warnings from tika + "ignore:pkg_resources is deprecated as an API:DeprecationWarning", + "ignore:Deprecated call to `pkg_resources.declare_namespace:DeprecationWarning" +] +markers = [ + "manual", # tests which should be triggered manual only + "noci", # tests which should not run on the CI + "regression", # tests which run a fuji as a whole + "smoke" # tests which run very fast +] +testpaths = "tests" + +[tool.ruff] +line-length = 120 +# Ref: https://docs.astral.sh/ruff/configuration/ +src = ["fuji_server"] +target-version = "py311" + +[tool.ruff.lint] +extend-select = [ + "I", # isort + "UP", # pyupgrade + "RUF" # ruff +] +ignore = [ + "E722", # bare-except + "RUF012" # mutable-class-default +] + +[tool.ruff.lint.isort] +known-first-party = ["fuji_server", "tests"] \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/gammapy/codemeta.json b/src/somef_core/test/test_data/repositories/gammapy/codemeta.json new file mode 100644 index 0000000..28bdd53 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/gammapy/codemeta.json @@ -0,0 +1,376 @@ +{ + "@context": "https://doi.org/10.5063/schema/codemeta-2.0", + "@type": "SoftwareSourceCode", + "author": [ + { + "@id": "https://orcid.org/0000-0002-6606-2816", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris-Saclay, Universit\u00e9 Paris Cit\u00e9, CEA, CNRS, AIM, F-91191 Gif-sur-Yvette, France" + }, + "familyName": "Acero", + "givenName": "Fabio" + }, + { + "@id": "https://orcid.org/0000-0001-8816-4920", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Departament de F\u00edsica Qu\u00e0ntica i Astrof\u00edsica, Institut de Ci\u00e8ncies del Cosmos, Universitat de Barcelona, IEEC-UB, Barcelona, Spain" + }, + "familyName": "Aguasca-Cabot", + "givenName": "Arnau" + }, + { + "@id": "https://orcid.org/0000-0002-8108-7552", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Centro de Investigaciones Energ\u00e9ticas Medioambientales y Tecnol\u00f3gicas (CIEMAT), Madrid, Spain" + }, + "familyName": "Bernete", + "givenName": "Juan" + }, + { + "@id": "https://orcid.org/0000-0003-3708-9785", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Astroparticle Physics Group, TU Dortmund University, Germany" + }, + "familyName": "Biederbeck", + "givenName": "Noah" + }, + { + "@id": "https://orcid.org/0000-0002-6488-8219", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "University of Bergen, Norway and Max Planck Institute for Nuclear Physics, Heidelberg, Germany" + }, + "familyName": "Djuvsland", + "givenName": "Julia" + }, + { + "@id": "https://orcid.org/0000-0003-4568-7005", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Center for Astrophysics | Harvard & Smithsonian, USA" + }, + "familyName": "Donath", + "givenName": "Axel" + }, + { + "@id": "https://orcid.org/0000-0003-1476-3714", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Feijen", + "givenName": "Kirsty" + }, + { + "@id": "https://orcid.org/0000-0003-1832-4129", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Astroparticle Physics Group, TU Dortmund University, Germany" + }, + "familyName": "Fr\u00f6se", + "givenName": "Stefan" + }, + { + "@id": "https://orcid.org/0000-0002-7372-9703", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Laboratoire Univers et Th\u00e9ories, Observatoire de Paris, Universit\u00e9 PSL,\\ \\ Universit\u00e9 Paris Cit\u00e9, CNRS, F-92190 Meudon, France" + }, + "familyName": "Galelli", + "givenName": "Claudio" + }, + { + "@id": "https://orcid.org/0000-0001-6876-5577", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Kh\u00e9lifi", + "givenName": "Bruno" + }, + { + "@id": "https://orcid.org/0009-0000-1257-4771", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Astroparticle Physics Group, TU Dortmund University, Germany" + }, + "familyName": "Konrad", + "givenName": "Jana" + }, + { + "@id": "https://orcid.org/0000-0002-2706-7438", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Laboratoire Univers et Th\u00e9ories, Observatoire de Paris, Universit\u00e9 PSL,\\ \\ Universit\u00e9 Paris Cit\u00e9, CNRS, F-92190 Meudon, France" + }, + "familyName": "Kornecki", + "givenName": "Paula" + }, + { + "@id": "https://orcid.org/0000-0001-7993-8189", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Astroparticle Physics Group, TU Dortmund University, Germany" + }, + "familyName": "Linhoff", + "givenName": "Maximilian" + }, + { + "@id": "https://orcid.org/0000-0002-8547-8489", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "University of Chicago, USA" + }, + "familyName": "McKee", + "givenName": "Kurt" + }, + { + "@id": "https://orcid.org/0000-0002-0755-0609", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Astroparticle Physics Group, TU Dortmund University, Germany" + }, + "familyName": "Mender", + "givenName": "Simone" + }, + { + "@id": "https://orcid.org/0000-0002-9667-8654", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Max Planck Institute for Nuclear Physics, Heidelberg, Germany" + }, + "familyName": "Mohrmann", + "givenName": "Lars" + }, + { + "@id": "https://orcid.org/0000-0001-9400-0922", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Instituto de Astrof\u00edsica de Andaluc\u00eda-CSIC, Granada, Spain" + }, + "familyName": "Morcuende", + "givenName": "Daniel" + }, + { + "@id": "https://orcid.org/0000-0002-8321-9168", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Instituto de Astrof\u00edsica de Canarias (IAC), C/ V\u00eda L\u00e1ctea s/n, 38205 La Laguna, Tenerife, Spain" + }, + "familyName": "Nievas Rosillo", + "givenName": "Mireia" + }, + { + "@id": "https://orcid.org/0000-0002-9105-0518", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Max Planck Institute for Nuclear Physics, Heidelberg, Germany" + }, + "familyName": "Olivera-Nieto", + "givenName": "Laura" + }, + { + "@id": "https://orcid.org/0000-0002-7537-7334", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Max-Planck-Institut f\u00fcr Physik, Boltzmannstra\u00dfe 8, 85748 Garching bei M\u00fcnchen, Germany" + }, + "familyName": "Peresano", + "givenName": "Michele" + }, + { + "@id": "https://orcid.org/0000-0002-3869-2925", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "INAF/IASF PALERMO, Italy" + }, + "familyName": "Pintore", + "givenName": "Fabio" + }, + { + "@id": "https://orcid.org/0000-0002-4710-2165", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Punch", + "givenName": "Michael" + }, + { + "@id": "https://orcid.org/0000-0002-3844-6003", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Regeard", + "givenName": "Maxime" + }, + { + "@id": "https://orcid.org/0000-0002-8815-6530", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Max Planck Institute for Nuclear Physics, Heidelberg, Germany" + }, + "familyName": "Remy", + "givenName": "Quentin" + }, + { + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Friedrich-Alexander-Universit\u00e4t Erlangen-N\u00fcrnberg, ECAP, Nikolaus-Fiebiger-Str. 2, 91058 Erlangen, Germany" + }, + "familyName": "Roellinghoff", + "givenName": "Gerrit" + }, + { + "@id": "https://orcid.org/0000-0002-9238-7163", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "EMFTEL department and IPARCOS, Universidad Complutense de Madrid, 28040 Madrid, Spain" + }, + "familyName": "Sinha", + "givenName": "Atreyee" + }, + { + "@id": "https://orcid.org/0000-0002-3713-6337", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Caltech/IPAC, USA" + }, + "familyName": "Sip\u0151cz", + "givenName": "Brigitta M" + }, + { + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Stapel", + "givenName": "Hanna" + }, + { + "@id": "https://orcid.org/0009-0005-7886-1825", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Friedrich-Alexander-Universit\u00e4t Erlangen-N\u00fcrnberg, ECAP, Nikolaus-Fiebiger-Str. 2, 91058 Erlangen, Germany" + }, + "familyName": "Streil", + "givenName": "Katrin" + }, + { + "@id": "https://orcid.org/0000-0002-8219-4667", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Terrier", + "givenName": "R\u00e9gis" + }, + { + "@id": "https://orcid.org/0000-0002-7378-4024", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Friedrich-Alexander-Universit\u00e4t Erlangen-N\u00fcrnberg, ECAP, Nikolaus-Fiebiger-Str. 2, 91058 Erlangen, Germany" + }, + "familyName": "Unbehaun", + "givenName": "Tim" + }, + { + "@id": "https://orcid.org/0000-0002-2730-2733", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Physics Department, McGill University, Montreal, QC H3A 2T8, Canada" + }, + "familyName": "Wong", + "givenName": "Samantha" + }, + { + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Universit\u00e9 Paris Cit\u00e9, CNRS, Astroparticule et Cosmologie, F-75013 Paris, France" + }, + "familyName": "Yu", + "givenName": "Pei" + } + ], + "codeRepository": "https://github.com/gammapy/gammapy", + "datePublished": "2024-11-26", + "description": "Gammapy analyzes gamma-ray data and creates sky images, spectra and lightcurves, from event lists and instrument response information; it can also determine the position, morphology and spectra of gamma-ray sources. It is used to analyze data from H.E.S.S., Fermi-LAT, HAWC, and the Cherenkov Telescope Array (CTA).", + "identifier": "https://doi.org/10.5281/zenodo.4701488", + "keywords": [ + "Astronomy", + "Gamma-rays", + "Data analysis" + ], + "license": "https://spdx.org/licenses/BSD-3-Clause", + "name": "Gammapy: Python toolbox for gamma-ray astronomy", + "url": "https://gammapy.org/", + "softwareVersion": "v1.3", + "maintainer": { + "@id": "https://orcid.org/0000-0003-4568-7005", + "@type": "Person", + "affiliation": { + "@type": "Organization", + "name": "Center for Astrophysics | Harvard & Smithsonian, USA" + }, + "familyName": "Donath", + "givenName": "Axel" + }, + "readme": "https://gammapy.org", + "issueTracker": "https://github.com/gammapy/gammapy/issues", + "developmentStatus": [ + "active" + ], + "email": "GAMMAPY-COORDINATION-L@IN2P3.FR", + + "dateModified": "2024-11-29", + + "softwareRequirements": [ + "numpy>=1.21", + "scipy>=1.5,!=1.10", + "astropy>=5.0", + "regions>=0.5.0", + "pyyaml>=5.3", + "click>=7.0", + "pydantic>=2.5.0", + "iminuit>=2.8.0", + "matplotlib>=3.4, <3.10" + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION b/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION new file mode 100644 index 0000000..63676ce --- /dev/null +++ b/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION @@ -0,0 +1,132 @@ +Package: ggplot2 +Title: Create Elegant Data Visualisations Using the Grammar of Graphics +Version: 4.0.0 +Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = "aut", + comment = c(ORCID = "0000-0003-4757-117X")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")), + person("Lionel", "Henry", role = "aut"), + person("Thomas Lin", "Pedersen", , "thomas.pedersen@posit.co", role = c("aut", "cre"), + comment = c(ORCID = "0000-0002-5147-4711")), + person("Kohske", "Takahashi", role = "aut"), + person("Claus", "Wilke", role = "aut", + comment = c(ORCID = "0000-0002-7470-9261")), + person("Kara", "Woo", role = "aut", + comment = c(ORCID = "0000-0002-5125-4188")), + person("Hiroaki", "Yutani", role = "aut", + comment = c(ORCID = "0000-0002-3385-7233")), + person("Dewey", "Dunnington", role = "aut", + comment = c(ORCID = "0000-0002-9415-4582")), + person("Teun", "van den Brand", role = "aut", + comment = c(ORCID = "0000-0002-9335-7468")), + person("Posit, PBC", role = c("cph", "fnd"), + comment = c(ROR = "03wc8by49")) + ) +Description: A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +License: MIT + file LICENSE +URL: https://ggplot2.tidyverse.org, + https://github.com/tidyverse/ggplot2 +BugReports: https://github.com/tidyverse/ggplot2/issues +Depends: R (>= 4.1) +Imports: cli, grDevices, grid, gtable (>= 0.3.6), isoband, lifecycle (> + 1.0.1), rlang (>= 1.1.0), S7, scales (>= 1.4.0), stats, vctrs + (>= 0.6.0), withr (>= 2.5.0) +Suggests: broom, covr, dplyr, ggplot2movies, hexbin, Hmisc, knitr, + mapproj, maps, MASS, mgcv, multcomp, munsell, nlme, profvis, + quantreg, ragg (>= 1.2.6), RColorBrewer, rmarkdown, roxygen2, + rpart, sf (>= 0.7-3), svglite (>= 2.1.2), testthat (>= 3.1.5), + tibble, vdiffr (>= 1.0.6), xml2 +Enhances: sp +VignetteBuilder: knitr +Config/Needs/website: ggtext, tidyr, forcats, tidyverse/tidytemplate +Config/testthat/edition: 3 +Config/usethis/last-upkeep: 2025-04-23 +Encoding: UTF-8 +LazyData: true +RoxygenNote: 7.3.2 +Collate: 'ggproto.R' 'ggplot-global.R' 'aaa-.R' + 'aes-colour-fill-alpha.R' 'aes-evaluation.R' + 'aes-group-order.R' 'aes-linetype-size-shape.R' + 'aes-position.R' 'all-classes.R' 'compat-plyr.R' 'utilities.R' + 'aes.R' 'annotation-borders.R' 'utilities-checks.R' + 'legend-draw.R' 'geom-.R' 'annotation-custom.R' + 'annotation-logticks.R' 'scale-type.R' 'layer.R' + 'make-constructor.R' 'geom-polygon.R' 'geom-map.R' + 'annotation-map.R' 'geom-raster.R' 'annotation-raster.R' + 'annotation.R' 'autolayer.R' 'autoplot.R' 'axis-secondary.R' + 'backports.R' 'bench.R' 'bin.R' 'coord-.R' 'coord-cartesian-.R' + 'coord-fixed.R' 'coord-flip.R' 'coord-map.R' 'coord-munch.R' + 'coord-polar.R' 'coord-quickmap.R' 'coord-radial.R' + 'coord-sf.R' 'coord-transform.R' 'data.R' 'docs_layer.R' + 'facet-.R' 'facet-grid-.R' 'facet-null.R' 'facet-wrap.R' + 'fortify-map.R' 'fortify-models.R' 'fortify-spatial.R' + 'fortify.R' 'stat-.R' 'geom-abline.R' 'geom-rect.R' + 'geom-bar.R' 'geom-tile.R' 'geom-bin2d.R' 'geom-blank.R' + 'geom-boxplot.R' 'geom-col.R' 'geom-path.R' 'geom-contour.R' + 'geom-point.R' 'geom-count.R' 'geom-crossbar.R' + 'geom-segment.R' 'geom-curve.R' 'geom-defaults.R' + 'geom-ribbon.R' 'geom-density.R' 'geom-density2d.R' + 'geom-dotplot.R' 'geom-errorbar.R' 'geom-freqpoly.R' + 'geom-function.R' 'geom-hex.R' 'geom-histogram.R' + 'geom-hline.R' 'geom-jitter.R' 'geom-label.R' + 'geom-linerange.R' 'geom-pointrange.R' 'geom-quantile.R' + 'geom-rug.R' 'geom-sf.R' 'geom-smooth.R' 'geom-spoke.R' + 'geom-text.R' 'geom-violin.R' 'geom-vline.R' + 'ggplot2-package.R' 'grob-absolute.R' 'grob-dotstack.R' + 'grob-null.R' 'grouping.R' 'properties.R' 'margins.R' + 'theme-elements.R' 'guide-.R' 'guide-axis.R' + 'guide-axis-logticks.R' 'guide-axis-stack.R' + 'guide-axis-theta.R' 'guide-legend.R' 'guide-bins.R' + 'guide-colorbar.R' 'guide-colorsteps.R' 'guide-custom.R' + 'guide-none.R' 'guide-old.R' 'guides-.R' 'guides-grid.R' + 'hexbin.R' 'import-standalone-obj-type.R' + 'import-standalone-types-check.R' 'labeller.R' 'labels.R' + 'layer-sf.R' 'layout.R' 'limits.R' 'performance.R' + 'plot-build.R' 'plot-construction.R' 'plot-last.R' 'plot.R' + 'position-.R' 'position-collide.R' 'position-dodge.R' + 'position-dodge2.R' 'position-identity.R' 'position-jitter.R' + 'position-jitterdodge.R' 'position-nudge.R' 'position-stack.R' + 'quick-plot.R' 'reshape-add-margins.R' 'save.R' 'scale-.R' + 'scale-alpha.R' 'scale-binned.R' 'scale-brewer.R' + 'scale-colour.R' 'scale-continuous.R' 'scale-date.R' + 'scale-discrete-.R' 'scale-expansion.R' 'scale-gradient.R' + 'scale-grey.R' 'scale-hue.R' 'scale-identity.R' + 'scale-linetype.R' 'scale-linewidth.R' 'scale-manual.R' + 'scale-shape.R' 'scale-size.R' 'scale-steps.R' 'scale-view.R' + 'scale-viridis.R' 'scales-.R' 'stat-align.R' 'stat-bin.R' + 'stat-summary-2d.R' 'stat-bin2d.R' 'stat-bindot.R' + 'stat-binhex.R' 'stat-boxplot.R' 'stat-connect.R' + 'stat-contour.R' 'stat-count.R' 'stat-density-2d.R' + 'stat-density.R' 'stat-ecdf.R' 'stat-ellipse.R' + 'stat-function.R' 'stat-identity.R' 'stat-manual.R' + 'stat-qq-line.R' 'stat-qq.R' 'stat-quantilemethods.R' + 'stat-sf-coordinates.R' 'stat-sf.R' 'stat-smooth-methods.R' + 'stat-smooth.R' 'stat-sum.R' 'stat-summary-bin.R' + 'stat-summary-hex.R' 'stat-summary.R' 'stat-unique.R' + 'stat-ydensity.R' 'summarise-plot.R' 'summary.R' 'theme.R' + 'theme-defaults.R' 'theme-current.R' 'theme-sub.R' + 'utilities-break.R' 'utilities-grid.R' 'utilities-help.R' + 'utilities-patterns.R' 'utilities-resolution.R' + 'utilities-tidy-eval.R' 'zxx.R' 'zzz.R' +NeedsCompilation: no +Packaged: 2025-08-19 08:21:45 UTC; thomas +Author: Hadley Wickham [aut] (ORCID: ), + Winston Chang [aut] (ORCID: ), + Lionel Henry [aut], + Thomas Lin Pedersen [aut, cre] (ORCID: + ), + Kohske Takahashi [aut], + Claus Wilke [aut] (ORCID: ), + Kara Woo [aut] (ORCID: ), + Hiroaki Yutani [aut] (ORCID: ), + Dewey Dunnington [aut] (ORCID: ), + Teun van den Brand [aut] (ORCID: + ), + Posit, PBC [cph, fnd] (ROR: ) +Maintainer: Thomas Lin Pedersen +Repository: CRAN +Date/Publication: 2025-09-11 07:10:02 UTC \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION 2 b/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION 2 new file mode 100644 index 0000000..63676ce --- /dev/null +++ b/src/somef_core/test/test_data/repositories/ggplot2/DESCRIPTION 2 @@ -0,0 +1,132 @@ +Package: ggplot2 +Title: Create Elegant Data Visualisations Using the Grammar of Graphics +Version: 4.0.0 +Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = "aut", + comment = c(ORCID = "0000-0003-4757-117X")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")), + person("Lionel", "Henry", role = "aut"), + person("Thomas Lin", "Pedersen", , "thomas.pedersen@posit.co", role = c("aut", "cre"), + comment = c(ORCID = "0000-0002-5147-4711")), + person("Kohske", "Takahashi", role = "aut"), + person("Claus", "Wilke", role = "aut", + comment = c(ORCID = "0000-0002-7470-9261")), + person("Kara", "Woo", role = "aut", + comment = c(ORCID = "0000-0002-5125-4188")), + person("Hiroaki", "Yutani", role = "aut", + comment = c(ORCID = "0000-0002-3385-7233")), + person("Dewey", "Dunnington", role = "aut", + comment = c(ORCID = "0000-0002-9415-4582")), + person("Teun", "van den Brand", role = "aut", + comment = c(ORCID = "0000-0002-9335-7468")), + person("Posit, PBC", role = c("cph", "fnd"), + comment = c(ROR = "03wc8by49")) + ) +Description: A system for 'declaratively' creating graphics, based on "The + Grammar of Graphics". You provide the data, tell 'ggplot2' how to map + variables to aesthetics, what graphical primitives to use, and it + takes care of the details. +License: MIT + file LICENSE +URL: https://ggplot2.tidyverse.org, + https://github.com/tidyverse/ggplot2 +BugReports: https://github.com/tidyverse/ggplot2/issues +Depends: R (>= 4.1) +Imports: cli, grDevices, grid, gtable (>= 0.3.6), isoband, lifecycle (> + 1.0.1), rlang (>= 1.1.0), S7, scales (>= 1.4.0), stats, vctrs + (>= 0.6.0), withr (>= 2.5.0) +Suggests: broom, covr, dplyr, ggplot2movies, hexbin, Hmisc, knitr, + mapproj, maps, MASS, mgcv, multcomp, munsell, nlme, profvis, + quantreg, ragg (>= 1.2.6), RColorBrewer, rmarkdown, roxygen2, + rpart, sf (>= 0.7-3), svglite (>= 2.1.2), testthat (>= 3.1.5), + tibble, vdiffr (>= 1.0.6), xml2 +Enhances: sp +VignetteBuilder: knitr +Config/Needs/website: ggtext, tidyr, forcats, tidyverse/tidytemplate +Config/testthat/edition: 3 +Config/usethis/last-upkeep: 2025-04-23 +Encoding: UTF-8 +LazyData: true +RoxygenNote: 7.3.2 +Collate: 'ggproto.R' 'ggplot-global.R' 'aaa-.R' + 'aes-colour-fill-alpha.R' 'aes-evaluation.R' + 'aes-group-order.R' 'aes-linetype-size-shape.R' + 'aes-position.R' 'all-classes.R' 'compat-plyr.R' 'utilities.R' + 'aes.R' 'annotation-borders.R' 'utilities-checks.R' + 'legend-draw.R' 'geom-.R' 'annotation-custom.R' + 'annotation-logticks.R' 'scale-type.R' 'layer.R' + 'make-constructor.R' 'geom-polygon.R' 'geom-map.R' + 'annotation-map.R' 'geom-raster.R' 'annotation-raster.R' + 'annotation.R' 'autolayer.R' 'autoplot.R' 'axis-secondary.R' + 'backports.R' 'bench.R' 'bin.R' 'coord-.R' 'coord-cartesian-.R' + 'coord-fixed.R' 'coord-flip.R' 'coord-map.R' 'coord-munch.R' + 'coord-polar.R' 'coord-quickmap.R' 'coord-radial.R' + 'coord-sf.R' 'coord-transform.R' 'data.R' 'docs_layer.R' + 'facet-.R' 'facet-grid-.R' 'facet-null.R' 'facet-wrap.R' + 'fortify-map.R' 'fortify-models.R' 'fortify-spatial.R' + 'fortify.R' 'stat-.R' 'geom-abline.R' 'geom-rect.R' + 'geom-bar.R' 'geom-tile.R' 'geom-bin2d.R' 'geom-blank.R' + 'geom-boxplot.R' 'geom-col.R' 'geom-path.R' 'geom-contour.R' + 'geom-point.R' 'geom-count.R' 'geom-crossbar.R' + 'geom-segment.R' 'geom-curve.R' 'geom-defaults.R' + 'geom-ribbon.R' 'geom-density.R' 'geom-density2d.R' + 'geom-dotplot.R' 'geom-errorbar.R' 'geom-freqpoly.R' + 'geom-function.R' 'geom-hex.R' 'geom-histogram.R' + 'geom-hline.R' 'geom-jitter.R' 'geom-label.R' + 'geom-linerange.R' 'geom-pointrange.R' 'geom-quantile.R' + 'geom-rug.R' 'geom-sf.R' 'geom-smooth.R' 'geom-spoke.R' + 'geom-text.R' 'geom-violin.R' 'geom-vline.R' + 'ggplot2-package.R' 'grob-absolute.R' 'grob-dotstack.R' + 'grob-null.R' 'grouping.R' 'properties.R' 'margins.R' + 'theme-elements.R' 'guide-.R' 'guide-axis.R' + 'guide-axis-logticks.R' 'guide-axis-stack.R' + 'guide-axis-theta.R' 'guide-legend.R' 'guide-bins.R' + 'guide-colorbar.R' 'guide-colorsteps.R' 'guide-custom.R' + 'guide-none.R' 'guide-old.R' 'guides-.R' 'guides-grid.R' + 'hexbin.R' 'import-standalone-obj-type.R' + 'import-standalone-types-check.R' 'labeller.R' 'labels.R' + 'layer-sf.R' 'layout.R' 'limits.R' 'performance.R' + 'plot-build.R' 'plot-construction.R' 'plot-last.R' 'plot.R' + 'position-.R' 'position-collide.R' 'position-dodge.R' + 'position-dodge2.R' 'position-identity.R' 'position-jitter.R' + 'position-jitterdodge.R' 'position-nudge.R' 'position-stack.R' + 'quick-plot.R' 'reshape-add-margins.R' 'save.R' 'scale-.R' + 'scale-alpha.R' 'scale-binned.R' 'scale-brewer.R' + 'scale-colour.R' 'scale-continuous.R' 'scale-date.R' + 'scale-discrete-.R' 'scale-expansion.R' 'scale-gradient.R' + 'scale-grey.R' 'scale-hue.R' 'scale-identity.R' + 'scale-linetype.R' 'scale-linewidth.R' 'scale-manual.R' + 'scale-shape.R' 'scale-size.R' 'scale-steps.R' 'scale-view.R' + 'scale-viridis.R' 'scales-.R' 'stat-align.R' 'stat-bin.R' + 'stat-summary-2d.R' 'stat-bin2d.R' 'stat-bindot.R' + 'stat-binhex.R' 'stat-boxplot.R' 'stat-connect.R' + 'stat-contour.R' 'stat-count.R' 'stat-density-2d.R' + 'stat-density.R' 'stat-ecdf.R' 'stat-ellipse.R' + 'stat-function.R' 'stat-identity.R' 'stat-manual.R' + 'stat-qq-line.R' 'stat-qq.R' 'stat-quantilemethods.R' + 'stat-sf-coordinates.R' 'stat-sf.R' 'stat-smooth-methods.R' + 'stat-smooth.R' 'stat-sum.R' 'stat-summary-bin.R' + 'stat-summary-hex.R' 'stat-summary.R' 'stat-unique.R' + 'stat-ydensity.R' 'summarise-plot.R' 'summary.R' 'theme.R' + 'theme-defaults.R' 'theme-current.R' 'theme-sub.R' + 'utilities-break.R' 'utilities-grid.R' 'utilities-help.R' + 'utilities-patterns.R' 'utilities-resolution.R' + 'utilities-tidy-eval.R' 'zxx.R' 'zzz.R' +NeedsCompilation: no +Packaged: 2025-08-19 08:21:45 UTC; thomas +Author: Hadley Wickham [aut] (ORCID: ), + Winston Chang [aut] (ORCID: ), + Lionel Henry [aut], + Thomas Lin Pedersen [aut, cre] (ORCID: + ), + Kohske Takahashi [aut], + Claus Wilke [aut] (ORCID: ), + Kara Woo [aut] (ORCID: ), + Hiroaki Yutani [aut] (ORCID: ), + Dewey Dunnington [aut] (ORCID: ), + Teun van den Brand [aut] (ORCID: + ), + Posit, PBC [cph, fnd] (ROR: ) +Maintainer: Thomas Lin Pedersen +Repository: CRAN +Date/Publication: 2025-09-11 07:10:02 UTC \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/haskell/cabal 2.cabal b/src/somef_core/test/test_data/repositories/haskell/cabal 2.cabal new file mode 100644 index 0000000..14c85b4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/haskell/cabal 2.cabal @@ -0,0 +1,419 @@ +cabal-version: 3.6 +name: Cabal +version: 3.17.0.0 +copyright: 2003-2025, Cabal Development Team (see AUTHORS file) +license: BSD-3-Clause +license-file: LICENSE +author: Cabal Development Team +maintainer: cabal-devel@haskell.org +homepage: http://www.haskell.org/cabal/ +bug-reports: https://github.com/haskell/cabal/issues +synopsis: A framework for packaging Haskell software +description: + The Haskell Common Architecture for Building Applications and + Libraries: a framework defining a common interface for authors to more + easily build their Haskell applications in a portable way. + . + The Haskell Cabal is part of a larger infrastructure for distributing, + organizing, and cataloging Haskell libraries and tools. +category: Distribution +build-type: Simple +-- If we use a new Cabal feature, this needs to be changed to Custom so +-- we can bootstrap. + +extra-doc-files: + README.md ChangeLog.md + +source-repository head + type: git + location: https://github.com/haskell/cabal/ + subdir: Cabal + +flag git-rev + description: include Git revision hash in version + default: False + manual: True + +library + default-language: Haskell2010 + hs-source-dirs: src + + build-depends: + , Cabal-syntax ^>= 3.17 + , array >= 0.4.0.1 && < 0.6 + , base >= 4.13 && < 5 + , bytestring >= 0.10.0.0 && < 0.13 + , containers >= 0.5.0.0 && < 0.9 + , deepseq >= 1.3.0.1 && < 1.7 + , directory >= 1.2 && < 1.4 + , filepath >= 1.3.0.1 && < 1.6 + , pretty >= 1.1.1 && < 1.2 + , process >= 1.2.1.0 && < 1.7 + , time >= 1.4.0.1 && < 1.16 + + if os(windows) + build-depends: + , Win32 >= 2.3.0.0 && < 2.15 + else + build-depends: + , unix >= 2.8.6.0 && < 2.9 + + if flag(git-rev) + build-depends: + , githash ^>= 0.1.7.0 + cpp-options: -DGIT_REV + + ghc-options: + -Wall + -fno-ignore-asserts + -Wtabs + -Wincomplete-uni-patterns + -Wincomplete-record-updates + -Wno-unticked-promoted-constructors + + if impl(ghc >= 8.0) + ghc-options: -Wcompat -Wnoncanonical-monad-instances + + if impl(ghc >= 8.0) && impl(ghc < 8.8) + ghc-options: -Wnoncanonical-monadfail-instances + + if impl(ghc >= 9.14) + ghc-options: -Wno-pattern-namespace-specifier -Wno-incomplete-record-selectors + + exposed-modules: + Distribution.Backpack.Configure + Distribution.Backpack.ComponentsGraph + Distribution.Backpack.ConfiguredComponent + Distribution.Backpack.DescribeUnitId + Distribution.Backpack.FullUnitId + Distribution.Backpack.LinkedComponent + Distribution.Backpack.ModSubst + Distribution.Backpack.ModuleShape + Distribution.Backpack.PreModuleShape + Distribution.Utils.IOData + Distribution.Utils.LogProgress + Distribution.Utils.MapAccum + Distribution.Compat.CreatePipe + Distribution.Compat.Directory + Distribution.Compat.Environment + Distribution.Compat.FilePath + Distribution.Compat.Internal.TempFile + Distribution.Compat.ResponseFile + Distribution.Compat.Prelude.Internal + Distribution.Compat.Process + Distribution.Compat.Stack + Distribution.Compat.Time + Distribution.Make + Distribution.PackageDescription.Check + Distribution.ReadE + Distribution.Simple + Distribution.Simple.Bench + Distribution.Simple.Build + Distribution.Simple.Build.Inputs + Distribution.Simple.Build.Macros + Distribution.Simple.Build.PackageInfoModule + Distribution.Simple.Build.PathsModule + Distribution.Simple.BuildPaths + Distribution.Simple.BuildTarget + Distribution.Simple.BuildToolDepends + Distribution.Simple.BuildWay + Distribution.Simple.CCompiler + Distribution.Simple.Command + Distribution.Simple.Compiler + Distribution.Simple.Configure + Distribution.Simple.Errors + Distribution.Simple.FileMonitor.Types + Distribution.Simple.Flag + Distribution.Simple.GHC + Distribution.Simple.GHCJS + Distribution.Simple.Haddock + Distribution.Simple.Glob + Distribution.Simple.Glob.Internal + Distribution.Simple.Hpc + Distribution.Simple.Install + Distribution.Simple.InstallDirs + Distribution.Simple.InstallDirs.Internal + Distribution.Simple.LocalBuildInfo + Distribution.Simple.PackageDescription + Distribution.Simple.PackageIndex + Distribution.Simple.PreProcess + Distribution.Simple.PreProcess.Types + Distribution.Simple.PreProcess.Unlit + Distribution.Simple.Program + Distribution.Simple.Program.Ar + Distribution.Simple.Program.Builtin + Distribution.Simple.Program.Db + Distribution.Simple.Program.Find + Distribution.Simple.Program.GHC + Distribution.Simple.Program.HcPkg + Distribution.Simple.Program.Hpc + Distribution.Simple.Program.Internal + Distribution.Simple.Program.Ld + Distribution.Simple.Program.ResponseFile + Distribution.Simple.Program.Run + Distribution.Simple.Program.Script + Distribution.Simple.Program.Strip + Distribution.Simple.Program.Types + Distribution.Simple.Register + Distribution.Simple.Setup + Distribution.Simple.ShowBuildInfo + Distribution.Simple.SrcDist + Distribution.Simple.Test + Distribution.Simple.Test.ExeV10 + Distribution.Simple.Test.LibV09 + Distribution.Simple.Test.Log + Distribution.Simple.UHC + Distribution.Simple.UserHooks + Distribution.Simple.SetupHooks.Errors + Distribution.Simple.SetupHooks.Internal + Distribution.Simple.SetupHooks.Rule + Distribution.Simple.Utils + Distribution.TestSuite + Distribution.Types.AnnotatedId + Distribution.Types.ComponentInclude + Distribution.Types.DumpBuildInfo + Distribution.Types.PackageName.Magic + Distribution.Types.ComponentLocalBuildInfo + Distribution.Types.LocalBuildConfig + Distribution.Types.LocalBuildInfo + Distribution.Types.TargetInfo + Distribution.Types.GivenComponent + Distribution.Types.ParStrat + Distribution.Utils.Json + Distribution.Utils.NubList + Distribution.Utils.Progress + Distribution.Verbosity + Distribution.Verbosity.Internal + + -- We reexport all of Cabal-syntax to aid in compatibility for downstream + -- users. In the future we may opt to deprecate some or all of these exports. + -- See haskell/Cabal#7974. + reexported-modules: + Distribution.Backpack, + Distribution.CabalSpecVersion, + Distribution.Compat.Binary, + Distribution.Compat.CharParsing, + Distribution.Compat.DList, + Distribution.Compat.Exception, + Distribution.Compat.Graph, + Distribution.Compat.Lens, + Distribution.Compat.MonadFail, + Distribution.Compat.Newtype, + Distribution.Compat.NonEmptySet, + Distribution.Compat.Parsing, + Distribution.Compat.Prelude, + Distribution.Compat.Semigroup, + Distribution.Compiler, + Distribution.FieldGrammar, + Distribution.FieldGrammar.Class, + Distribution.FieldGrammar.FieldDescrs, + Distribution.FieldGrammar.Newtypes, + Distribution.FieldGrammar.Parsec, + Distribution.FieldGrammar.Pretty, + Distribution.Fields, + Distribution.Fields.ConfVar, + Distribution.Fields.Field, + Distribution.Fields.Lexer, + Distribution.Fields.LexerMonad, + Distribution.Fields.ParseResult, + Distribution.Fields.Parser, + Distribution.Fields.Pretty, + Distribution.InstalledPackageInfo, + Distribution.License, + Distribution.ModuleName, + Distribution.Package, + Distribution.PackageDescription, + Distribution.PackageDescription.Configuration, + Distribution.PackageDescription.FieldGrammar, + Distribution.PackageDescription.Parsec, + Distribution.PackageDescription.PrettyPrint, + Distribution.PackageDescription.Quirks, + Distribution.PackageDescription.Utils, + Distribution.Parsec, + Distribution.Parsec.Error, + Distribution.Parsec.FieldLineStream, + Distribution.Parsec.Position, + Distribution.Parsec.Warning, + Distribution.Pretty, + Distribution.SPDX, + Distribution.SPDX.License, + Distribution.SPDX.LicenseExceptionId, + Distribution.SPDX.LicenseExpression, + Distribution.SPDX.LicenseId, + Distribution.SPDX.LicenseListVersion, + Distribution.SPDX.LicenseReference, + Distribution.System, + Distribution.Text, + Distribution.Types.AbiDependency, + Distribution.Types.AbiHash, + Distribution.Types.Benchmark, + Distribution.Types.Benchmark.Lens, + Distribution.Types.BenchmarkInterface, + Distribution.Types.BenchmarkType, + Distribution.Types.BuildInfo, + Distribution.Types.BuildInfo.Lens, + Distribution.Types.BuildType, + Distribution.Types.Component, + Distribution.Types.ComponentId, + Distribution.Types.ComponentName, + Distribution.Types.ComponentRequestedSpec, + Distribution.Types.CondTree, + Distribution.Types.Condition, + Distribution.Types.ConfVar, + Distribution.Types.Dependency, + Distribution.Types.DependencyMap, + Distribution.Types.DependencySatisfaction, + Distribution.Types.ExeDependency, + Distribution.Types.Executable, + Distribution.Types.Executable.Lens, + Distribution.Types.ExecutableScope, + Distribution.Types.ExposedModule, + Distribution.Types.Flag, + Distribution.Types.ForeignLib, + Distribution.Types.ForeignLib.Lens, + Distribution.Types.ForeignLibOption, + Distribution.Types.ForeignLibType, + Distribution.Types.GenericPackageDescription, + Distribution.Types.GenericPackageDescription.Lens, + Distribution.Types.HookedBuildInfo, + Distribution.Types.IncludeRenaming, + Distribution.Types.InstalledPackageInfo, + Distribution.Types.InstalledPackageInfo.Lens, + Distribution.Types.InstalledPackageInfo.FieldGrammar, + Distribution.Types.LegacyExeDependency, + Distribution.Types.Lens, + Distribution.Types.Library, + Distribution.Types.Library.Lens, + Distribution.Types.LibraryName, + Distribution.Types.LibraryVisibility, + Distribution.Types.MissingDependency, + Distribution.Types.MissingDependencyReason, + Distribution.Types.Mixin, + Distribution.Types.Module, + Distribution.Types.ModuleReexport, + Distribution.Types.ModuleRenaming, + Distribution.Types.MungedPackageId, + Distribution.Types.MungedPackageName, + Distribution.Types.PackageDescription, + Distribution.Types.PackageDescription.Lens, + Distribution.Types.PackageId, + Distribution.Types.PackageId.Lens, + Distribution.Types.PackageName, + Distribution.Types.PackageVersionConstraint, + Distribution.Types.PkgconfigDependency, + Distribution.Types.PkgconfigName, + Distribution.Types.PkgconfigVersion, + Distribution.Types.PkgconfigVersionRange, + Distribution.Types.SetupBuildInfo, + Distribution.Types.SetupBuildInfo.Lens, + Distribution.Types.SourceRepo, + Distribution.Types.SourceRepo.Lens, + Distribution.Types.TestSuite, + Distribution.Types.TestSuite.Lens, + Distribution.Types.TestSuiteInterface, + Distribution.Types.TestType, + Distribution.Types.UnitId, + Distribution.Types.UnqualComponentName, + Distribution.Types.Version, + Distribution.Types.VersionInterval, + Distribution.Types.VersionInterval.Legacy, + Distribution.Types.VersionRange, + Distribution.Types.VersionRange.Internal, + Distribution.Utils.Base62, + Distribution.Utils.Generic, + Distribution.Utils.MD5, + Distribution.Utils.Path, + Distribution.Utils.ShortText, + Distribution.Utils.String, + Distribution.Utils.Structured, + Distribution.Version, + Language.Haskell.Extension + + -- Parsec parser-related modules + build-depends: + -- transformers-0.4.0.0 doesn't have record syntax e.g. for Identity + -- See also https://github.com/ekmett/transformers-compat/issues/35 + , transformers (>= 0.3 && < 0.4) || (>=0.4.1.0 && <0.7) + , mtl >= 2.1 && < 2.4 + , parsec >= 3.1.13.0 && < 3.2 + + other-modules: + Distribution.Backpack.PreExistingComponent + Distribution.Backpack.ReadyComponent + Distribution.Backpack.MixLink + Distribution.Backpack.ModuleScope + Distribution.Backpack.UnifyM + Distribution.Backpack.Id + Distribution.Utils.UnionFind + Distribution.Compat.Async + Distribution.Compat.CopyFile + Distribution.Compat.GetShortPathName + Distribution.Compat.SnocList + Distribution.GetOpt + Distribution.Lex + Distribution.PackageDescription.Check.Common + Distribution.PackageDescription.Check.Conditional + Distribution.PackageDescription.Check.Monad + Distribution.PackageDescription.Check.Paths + Distribution.PackageDescription.Check.Target + Distribution.PackageDescription.Check.Warning + Distribution.Simple.Build.Macros.Z + Distribution.Simple.Build.PackageInfoModule.Z + Distribution.Simple.Build.PathsModule.Z + Distribution.Simple.GHC.Build + Distribution.Simple.GHC.Build.ExtraSources + Distribution.Simple.GHC.Build.Link + Distribution.Simple.GHC.Build.Modules + Distribution.Simple.GHC.Build.Utils + Distribution.Simple.GHC.EnvironmentParser + Distribution.Simple.GHC.Internal + Distribution.Simple.GHC.ImplInfo + Distribution.Simple.ConfigureScript + Distribution.Simple.Setup.Benchmark + Distribution.Simple.Setup.Build + Distribution.Simple.Setup.Clean + Distribution.Simple.Setup.Common + Distribution.Simple.Setup.Config + Distribution.Simple.Setup.Copy + Distribution.Simple.Setup.Global + Distribution.Simple.Setup.Haddock + Distribution.Simple.Setup.Hscolour + Distribution.Simple.Setup.Install + Distribution.Simple.Setup.Register + Distribution.Simple.Setup.Repl + Distribution.Simple.Setup.SDist + Distribution.Simple.Setup.Test + Distribution.ZinzaPrelude + Paths_Cabal + + autogen-modules: + Paths_Cabal + + other-extensions: + BangPatterns + CPP + DefaultSignatures + DeriveDataTypeable + DeriveFoldable + DeriveFunctor + DeriveGeneric + DeriveTraversable + ExistentialQuantification + FlexibleContexts + FlexibleInstances + GeneralizedNewtypeDeriving + ImplicitParams + KindSignatures + LambdaCase + NondecreasingIndentation + OverloadedStrings + PatternSynonyms + RankNTypes + RecordWildCards + ScopedTypeVariables + StandaloneDeriving + Trustworthy + TypeFamilies + TypeOperators + TypeSynonymInstances + UndecidableInstances \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/haskell/cabal.cabal b/src/somef_core/test/test_data/repositories/haskell/cabal.cabal new file mode 100644 index 0000000..14c85b4 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/haskell/cabal.cabal @@ -0,0 +1,419 @@ +cabal-version: 3.6 +name: Cabal +version: 3.17.0.0 +copyright: 2003-2025, Cabal Development Team (see AUTHORS file) +license: BSD-3-Clause +license-file: LICENSE +author: Cabal Development Team +maintainer: cabal-devel@haskell.org +homepage: http://www.haskell.org/cabal/ +bug-reports: https://github.com/haskell/cabal/issues +synopsis: A framework for packaging Haskell software +description: + The Haskell Common Architecture for Building Applications and + Libraries: a framework defining a common interface for authors to more + easily build their Haskell applications in a portable way. + . + The Haskell Cabal is part of a larger infrastructure for distributing, + organizing, and cataloging Haskell libraries and tools. +category: Distribution +build-type: Simple +-- If we use a new Cabal feature, this needs to be changed to Custom so +-- we can bootstrap. + +extra-doc-files: + README.md ChangeLog.md + +source-repository head + type: git + location: https://github.com/haskell/cabal/ + subdir: Cabal + +flag git-rev + description: include Git revision hash in version + default: False + manual: True + +library + default-language: Haskell2010 + hs-source-dirs: src + + build-depends: + , Cabal-syntax ^>= 3.17 + , array >= 0.4.0.1 && < 0.6 + , base >= 4.13 && < 5 + , bytestring >= 0.10.0.0 && < 0.13 + , containers >= 0.5.0.0 && < 0.9 + , deepseq >= 1.3.0.1 && < 1.7 + , directory >= 1.2 && < 1.4 + , filepath >= 1.3.0.1 && < 1.6 + , pretty >= 1.1.1 && < 1.2 + , process >= 1.2.1.0 && < 1.7 + , time >= 1.4.0.1 && < 1.16 + + if os(windows) + build-depends: + , Win32 >= 2.3.0.0 && < 2.15 + else + build-depends: + , unix >= 2.8.6.0 && < 2.9 + + if flag(git-rev) + build-depends: + , githash ^>= 0.1.7.0 + cpp-options: -DGIT_REV + + ghc-options: + -Wall + -fno-ignore-asserts + -Wtabs + -Wincomplete-uni-patterns + -Wincomplete-record-updates + -Wno-unticked-promoted-constructors + + if impl(ghc >= 8.0) + ghc-options: -Wcompat -Wnoncanonical-monad-instances + + if impl(ghc >= 8.0) && impl(ghc < 8.8) + ghc-options: -Wnoncanonical-monadfail-instances + + if impl(ghc >= 9.14) + ghc-options: -Wno-pattern-namespace-specifier -Wno-incomplete-record-selectors + + exposed-modules: + Distribution.Backpack.Configure + Distribution.Backpack.ComponentsGraph + Distribution.Backpack.ConfiguredComponent + Distribution.Backpack.DescribeUnitId + Distribution.Backpack.FullUnitId + Distribution.Backpack.LinkedComponent + Distribution.Backpack.ModSubst + Distribution.Backpack.ModuleShape + Distribution.Backpack.PreModuleShape + Distribution.Utils.IOData + Distribution.Utils.LogProgress + Distribution.Utils.MapAccum + Distribution.Compat.CreatePipe + Distribution.Compat.Directory + Distribution.Compat.Environment + Distribution.Compat.FilePath + Distribution.Compat.Internal.TempFile + Distribution.Compat.ResponseFile + Distribution.Compat.Prelude.Internal + Distribution.Compat.Process + Distribution.Compat.Stack + Distribution.Compat.Time + Distribution.Make + Distribution.PackageDescription.Check + Distribution.ReadE + Distribution.Simple + Distribution.Simple.Bench + Distribution.Simple.Build + Distribution.Simple.Build.Inputs + Distribution.Simple.Build.Macros + Distribution.Simple.Build.PackageInfoModule + Distribution.Simple.Build.PathsModule + Distribution.Simple.BuildPaths + Distribution.Simple.BuildTarget + Distribution.Simple.BuildToolDepends + Distribution.Simple.BuildWay + Distribution.Simple.CCompiler + Distribution.Simple.Command + Distribution.Simple.Compiler + Distribution.Simple.Configure + Distribution.Simple.Errors + Distribution.Simple.FileMonitor.Types + Distribution.Simple.Flag + Distribution.Simple.GHC + Distribution.Simple.GHCJS + Distribution.Simple.Haddock + Distribution.Simple.Glob + Distribution.Simple.Glob.Internal + Distribution.Simple.Hpc + Distribution.Simple.Install + Distribution.Simple.InstallDirs + Distribution.Simple.InstallDirs.Internal + Distribution.Simple.LocalBuildInfo + Distribution.Simple.PackageDescription + Distribution.Simple.PackageIndex + Distribution.Simple.PreProcess + Distribution.Simple.PreProcess.Types + Distribution.Simple.PreProcess.Unlit + Distribution.Simple.Program + Distribution.Simple.Program.Ar + Distribution.Simple.Program.Builtin + Distribution.Simple.Program.Db + Distribution.Simple.Program.Find + Distribution.Simple.Program.GHC + Distribution.Simple.Program.HcPkg + Distribution.Simple.Program.Hpc + Distribution.Simple.Program.Internal + Distribution.Simple.Program.Ld + Distribution.Simple.Program.ResponseFile + Distribution.Simple.Program.Run + Distribution.Simple.Program.Script + Distribution.Simple.Program.Strip + Distribution.Simple.Program.Types + Distribution.Simple.Register + Distribution.Simple.Setup + Distribution.Simple.ShowBuildInfo + Distribution.Simple.SrcDist + Distribution.Simple.Test + Distribution.Simple.Test.ExeV10 + Distribution.Simple.Test.LibV09 + Distribution.Simple.Test.Log + Distribution.Simple.UHC + Distribution.Simple.UserHooks + Distribution.Simple.SetupHooks.Errors + Distribution.Simple.SetupHooks.Internal + Distribution.Simple.SetupHooks.Rule + Distribution.Simple.Utils + Distribution.TestSuite + Distribution.Types.AnnotatedId + Distribution.Types.ComponentInclude + Distribution.Types.DumpBuildInfo + Distribution.Types.PackageName.Magic + Distribution.Types.ComponentLocalBuildInfo + Distribution.Types.LocalBuildConfig + Distribution.Types.LocalBuildInfo + Distribution.Types.TargetInfo + Distribution.Types.GivenComponent + Distribution.Types.ParStrat + Distribution.Utils.Json + Distribution.Utils.NubList + Distribution.Utils.Progress + Distribution.Verbosity + Distribution.Verbosity.Internal + + -- We reexport all of Cabal-syntax to aid in compatibility for downstream + -- users. In the future we may opt to deprecate some or all of these exports. + -- See haskell/Cabal#7974. + reexported-modules: + Distribution.Backpack, + Distribution.CabalSpecVersion, + Distribution.Compat.Binary, + Distribution.Compat.CharParsing, + Distribution.Compat.DList, + Distribution.Compat.Exception, + Distribution.Compat.Graph, + Distribution.Compat.Lens, + Distribution.Compat.MonadFail, + Distribution.Compat.Newtype, + Distribution.Compat.NonEmptySet, + Distribution.Compat.Parsing, + Distribution.Compat.Prelude, + Distribution.Compat.Semigroup, + Distribution.Compiler, + Distribution.FieldGrammar, + Distribution.FieldGrammar.Class, + Distribution.FieldGrammar.FieldDescrs, + Distribution.FieldGrammar.Newtypes, + Distribution.FieldGrammar.Parsec, + Distribution.FieldGrammar.Pretty, + Distribution.Fields, + Distribution.Fields.ConfVar, + Distribution.Fields.Field, + Distribution.Fields.Lexer, + Distribution.Fields.LexerMonad, + Distribution.Fields.ParseResult, + Distribution.Fields.Parser, + Distribution.Fields.Pretty, + Distribution.InstalledPackageInfo, + Distribution.License, + Distribution.ModuleName, + Distribution.Package, + Distribution.PackageDescription, + Distribution.PackageDescription.Configuration, + Distribution.PackageDescription.FieldGrammar, + Distribution.PackageDescription.Parsec, + Distribution.PackageDescription.PrettyPrint, + Distribution.PackageDescription.Quirks, + Distribution.PackageDescription.Utils, + Distribution.Parsec, + Distribution.Parsec.Error, + Distribution.Parsec.FieldLineStream, + Distribution.Parsec.Position, + Distribution.Parsec.Warning, + Distribution.Pretty, + Distribution.SPDX, + Distribution.SPDX.License, + Distribution.SPDX.LicenseExceptionId, + Distribution.SPDX.LicenseExpression, + Distribution.SPDX.LicenseId, + Distribution.SPDX.LicenseListVersion, + Distribution.SPDX.LicenseReference, + Distribution.System, + Distribution.Text, + Distribution.Types.AbiDependency, + Distribution.Types.AbiHash, + Distribution.Types.Benchmark, + Distribution.Types.Benchmark.Lens, + Distribution.Types.BenchmarkInterface, + Distribution.Types.BenchmarkType, + Distribution.Types.BuildInfo, + Distribution.Types.BuildInfo.Lens, + Distribution.Types.BuildType, + Distribution.Types.Component, + Distribution.Types.ComponentId, + Distribution.Types.ComponentName, + Distribution.Types.ComponentRequestedSpec, + Distribution.Types.CondTree, + Distribution.Types.Condition, + Distribution.Types.ConfVar, + Distribution.Types.Dependency, + Distribution.Types.DependencyMap, + Distribution.Types.DependencySatisfaction, + Distribution.Types.ExeDependency, + Distribution.Types.Executable, + Distribution.Types.Executable.Lens, + Distribution.Types.ExecutableScope, + Distribution.Types.ExposedModule, + Distribution.Types.Flag, + Distribution.Types.ForeignLib, + Distribution.Types.ForeignLib.Lens, + Distribution.Types.ForeignLibOption, + Distribution.Types.ForeignLibType, + Distribution.Types.GenericPackageDescription, + Distribution.Types.GenericPackageDescription.Lens, + Distribution.Types.HookedBuildInfo, + Distribution.Types.IncludeRenaming, + Distribution.Types.InstalledPackageInfo, + Distribution.Types.InstalledPackageInfo.Lens, + Distribution.Types.InstalledPackageInfo.FieldGrammar, + Distribution.Types.LegacyExeDependency, + Distribution.Types.Lens, + Distribution.Types.Library, + Distribution.Types.Library.Lens, + Distribution.Types.LibraryName, + Distribution.Types.LibraryVisibility, + Distribution.Types.MissingDependency, + Distribution.Types.MissingDependencyReason, + Distribution.Types.Mixin, + Distribution.Types.Module, + Distribution.Types.ModuleReexport, + Distribution.Types.ModuleRenaming, + Distribution.Types.MungedPackageId, + Distribution.Types.MungedPackageName, + Distribution.Types.PackageDescription, + Distribution.Types.PackageDescription.Lens, + Distribution.Types.PackageId, + Distribution.Types.PackageId.Lens, + Distribution.Types.PackageName, + Distribution.Types.PackageVersionConstraint, + Distribution.Types.PkgconfigDependency, + Distribution.Types.PkgconfigName, + Distribution.Types.PkgconfigVersion, + Distribution.Types.PkgconfigVersionRange, + Distribution.Types.SetupBuildInfo, + Distribution.Types.SetupBuildInfo.Lens, + Distribution.Types.SourceRepo, + Distribution.Types.SourceRepo.Lens, + Distribution.Types.TestSuite, + Distribution.Types.TestSuite.Lens, + Distribution.Types.TestSuiteInterface, + Distribution.Types.TestType, + Distribution.Types.UnitId, + Distribution.Types.UnqualComponentName, + Distribution.Types.Version, + Distribution.Types.VersionInterval, + Distribution.Types.VersionInterval.Legacy, + Distribution.Types.VersionRange, + Distribution.Types.VersionRange.Internal, + Distribution.Utils.Base62, + Distribution.Utils.Generic, + Distribution.Utils.MD5, + Distribution.Utils.Path, + Distribution.Utils.ShortText, + Distribution.Utils.String, + Distribution.Utils.Structured, + Distribution.Version, + Language.Haskell.Extension + + -- Parsec parser-related modules + build-depends: + -- transformers-0.4.0.0 doesn't have record syntax e.g. for Identity + -- See also https://github.com/ekmett/transformers-compat/issues/35 + , transformers (>= 0.3 && < 0.4) || (>=0.4.1.0 && <0.7) + , mtl >= 2.1 && < 2.4 + , parsec >= 3.1.13.0 && < 3.2 + + other-modules: + Distribution.Backpack.PreExistingComponent + Distribution.Backpack.ReadyComponent + Distribution.Backpack.MixLink + Distribution.Backpack.ModuleScope + Distribution.Backpack.UnifyM + Distribution.Backpack.Id + Distribution.Utils.UnionFind + Distribution.Compat.Async + Distribution.Compat.CopyFile + Distribution.Compat.GetShortPathName + Distribution.Compat.SnocList + Distribution.GetOpt + Distribution.Lex + Distribution.PackageDescription.Check.Common + Distribution.PackageDescription.Check.Conditional + Distribution.PackageDescription.Check.Monad + Distribution.PackageDescription.Check.Paths + Distribution.PackageDescription.Check.Target + Distribution.PackageDescription.Check.Warning + Distribution.Simple.Build.Macros.Z + Distribution.Simple.Build.PackageInfoModule.Z + Distribution.Simple.Build.PathsModule.Z + Distribution.Simple.GHC.Build + Distribution.Simple.GHC.Build.ExtraSources + Distribution.Simple.GHC.Build.Link + Distribution.Simple.GHC.Build.Modules + Distribution.Simple.GHC.Build.Utils + Distribution.Simple.GHC.EnvironmentParser + Distribution.Simple.GHC.Internal + Distribution.Simple.GHC.ImplInfo + Distribution.Simple.ConfigureScript + Distribution.Simple.Setup.Benchmark + Distribution.Simple.Setup.Build + Distribution.Simple.Setup.Clean + Distribution.Simple.Setup.Common + Distribution.Simple.Setup.Config + Distribution.Simple.Setup.Copy + Distribution.Simple.Setup.Global + Distribution.Simple.Setup.Haddock + Distribution.Simple.Setup.Hscolour + Distribution.Simple.Setup.Install + Distribution.Simple.Setup.Register + Distribution.Simple.Setup.Repl + Distribution.Simple.Setup.SDist + Distribution.Simple.Setup.Test + Distribution.ZinzaPrelude + Paths_Cabal + + autogen-modules: + Paths_Cabal + + other-extensions: + BangPatterns + CPP + DefaultSignatures + DeriveDataTypeable + DeriveFoldable + DeriveFunctor + DeriveGeneric + DeriveTraversable + ExistentialQuantification + FlexibleContexts + FlexibleInstances + GeneralizedNewtypeDeriving + ImplicitParams + KindSignatures + LambdaCase + NondecreasingIndentation + OverloadedStrings + PatternSynonyms + RankNTypes + RecordWildCards + ScopedTypeVariables + StandaloneDeriving + Trustworthy + TypeFamilies + TypeOperators + TypeSynonymInstances + UndecidableInstances \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/inspect4py/CITATION.cff b/src/somef_core/test/test_data/repositories/inspect4py/CITATION.cff new file mode 100644 index 0000000..71a03d0 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/inspect4py/CITATION.cff @@ -0,0 +1,25 @@ +title: "Inspect4py: A Knowledge Extraction Framework for Python Code Repositories" +license: BSD-3-Clause license +authors: + - family-names: Filgueira + given-names: Rosa + orcid: "0000-0002-5715-3046" + - family-names: Garijo + given-names: Daniel + orcid: "http://orcid.org/0000-0003-0454-7145" +cff-version: 1.2.0 +message: "If you use this software, please cite both the article from preferred-citation and the software itself." +preferred-citation: + authors: + - family-names: Filgueira + given-names: Rosa + - family-names: Garijo + given-names: Daniel + title: "Inspect4py: A Knowledge Extraction Framework for Python Code Repositories" + type: article + year: 2022 + doi: 10.1145/3524842.3528497 +identifiers: + - description: "Collection of archived snapshots for Inspect4py" + type: doi + value: 10.5281/zenodo.5907936 \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/inspect4py/README 2.md b/src/somef_core/test/test_data/repositories/inspect4py/README 2.md new file mode 100644 index 0000000..f872340 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/inspect4py/README 2.md @@ -0,0 +1,255 @@ +# inspect4py +[![PyPI](https://badge.fury.io/py/inspect4py.svg)](https://badge.fury.io/py/inspect4py) [![DOI](https://zenodo.org/badge/349160905.svg)](https://zenodo.org/badge/latestdoi/349160905) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) + +logo + +Library to allow users inspect a software project folder (i.e., a directory and its subdirectories) and extract all the most relevant information, such as class, method and parameter documentation, classes (and their methods), functions, etc. + +## Features: + +Given a folder with code, `inspect4py` will: + +- Extract all imported modules and how each module is imported as (i.e., whether they are internal or external). +- Extract all functions in the code, including their documentation, parameters, accepted values, and call list. +- Extract all classes in the code, with all their methods and respective documentation +- Extract the control flow of each file. +- Extract the hierarchy of directories and files. +- Extract the requirements used in the software project. +- Classify which files are tests +- Classify the main type of software project (script, package, library or service). Only one type is returned as main type (e.g., if a library has the option to be deployed as a service, `inspect4py` will return `Library` as its main type) +- Return a ranking of the different ways in which a a software component can be run, ordered by relevance. + + +All metadata is extracted as a JSON file. + + +Inspect4py currently works **only for Python 3 projects**. + +## Background: + +`inspect4py` added the functionality of capture [Data Flow Graphs](http://bears.ece.ucsb.edu/research-info/DP/dfg.html) for each function inspired by GraphCodeBERT: [Github](https://github.com/microsoft/CodeBERT) & [Paper](https://arxiv.org/abs/2009.08366). The illustration is given: +|Source Code|List Output|Networkx Image| +|:-:|:-:|:-:| +|
def max(a, b):
x = 0
if a > b:
x = a
else:
x = b
return x
|
('a', 3, 'comesFrom', [], [])
('b', 5, 'comesFrom', [], [])
('x', 8, 'computedFrom', ['0'], [10])
('0', 10, 'comesFrom', [], [])
('a', 12, 'comesFrom', ['a'], [3])
('b', 14, 'comesFrom', ['b'], [5])
('x', 16, 'computedFrom', ['a'], [18])
('a', 18, 'comesFrom', ['a'], [3])
('x', 21, 'computedFrom', ['b'], [23])
('b', 23, 'comesFrom', ['b'], [5])
('x', 25, 'comesFrom', ['x'], [16, 21])
|![image](docs/images/data_flow.png)| + +`inspect4py` uses [ASTs](https://en.wikipedia.org/wiki/Abstract_syntax_tree), more specifically +the [ast](https://docs.python.org/3/library/ast.html) module in Python, generating +a tree of objects (per file) whose classes all inherit from [ast.AST](https://docs.python.org/3/library/ast.html#ast.AST). + +`inspect4py` parses each of the input file(s) as an AST tree, extracting the relevant information and storing it as a JSON file. Furthermore, it also captures the control flow of each input file(s), by using another two libraries: + +- [staticfg](inspect4py/staticfg): StatiCFG is a package that can be used to produce control flow graphs (CFGs) for Python 3 programs. The CFGs it generates can be easily visualised with graphviz and used for static analysis. We have a flag in the code (FLAG_PNG) to indicate if we want to generate this type of control flow graphs or not. **Note**: The original code of this package can be found [here](https://github.com/coetaur0/staticfg), which has been fixed it in our [repository](inspect4py/staticfg) + +We also use [docstring_parser](https://pypi.org/project/docstring-parser/), which has support for ReST, Google, and Numpydoc-style docstrings. Some (basic) tests done using this library can be found at [here](./test_docstring_parser/). + +Finally, we reuse [Pigar](https://github.com/damnever/pigar) for generating automatically the requirements of a given repository. This is an optional funcionality. In order to activate the argument (`-r`) has to be indicated when running inspect4py. + +## Cite inspect4py +Please cite our MSR 2022 demo paper: +``` +@inproceedings{FilgueiraG22, + author = {Rosa Filgueira and + Daniel Garijo}, + title = {Inspect4py: {A} Knowledge Extraction Framework for Python Code Repositories}, + booktitle = {{IEEE/ACM} 19th International Conference on Mining Software Repositories, + {MSR} 2022, Pittsburgh, PA, USA, May 23-24, 2022}, + pages = {232--236}, + publisher = {{IEEE}}, + year = {2022}, + url = {https://dgarijo.com/papers/inspect4py_MSR2022.pdf}, + doi = {10.1145/3524842.3528497} +} +``` + +## Install + +### Preliminaries + +Make sure you have tree-sitter installed, C complier is needed, more [info](https://github.com/tree-sitter/tree-sitter): + +``` +pip install tree-sitter +``` +Note that if the ".so" file is not working properly, it is recommended that run the following commeds to generate a so file for your OS: +``` +git clone https://github.com/tree-sitter/tree-sitter-python + +python inspect4py/build.py +``` + +Make sure you have graphviz installed: + +``` +sudo apt-get install graphviz +``` + +### Python version +We have tested `inspect4py` in Python 3.7+. **Our recommended version is Python 3.9**. + + +### Operative System +We have tested `inspect4py` in Unix, MacOS and Windows 11(22621.1265). + +### Installation from pypi +`inspect4py` is [available in pypi!](https://pypi.org/project/inspect4py/) Just install it like a regular package: + +``` +pip install inspect4py +``` + +You are done! + +Then try to update the python-dev utilities: `sudo apt-get install python3.X-dev` (where X is your python version) + +### Installation from code + +Prepare a virtual Python3 enviroment, `cd` into the `inspect4py` folder and install the package as follows: + +``` +git clone https://github.com/SoftwareUnderstanding/inspect4py +cd inspect4py +pip install -e . +``` + +You are done! + +### Package dependencies: +``` +docstring_parser==0.7 +astor +graphviz +click +pigar +setuptools==54.2.0 +json2html +configparser +bigcode_astgen +GitPython +tree-sitter +``` + +If you want to run the evaluations, do not forget to add `pandas` to the previous set. + +### Installation through Docker + +You need to have [Docker](https://docs.docker.com/get-started/) installed. + +Next, clone the `inspect4py` repository: + +``` +git clone https://github.com/SoftwareUnderstanding/inspect4py/ +``` + +Generate a Docker image for `inspect4py`: + +``` +docker build --tag inspect4py:1.0 . +``` + +Run the `inspect4py` image: + +``` +docker run -it --rm inspect4py:1.0 /bin/bash +``` + +Now you can run `inspect4py`: +``` +root@e04792563e6a:/# inspect4py --help +``` + +For more information about `inspect4py` execution options, please see the section below (Execution). + +Note that when running `inspect4py` with Docker, you will need to need to provide a path to the target repository to analyze. You can do this by: + +1. Cloning the target repository. For example: + +``` +docker run -it --rm inspect4py:1.0 /bin/bash +# Docker image starts +root@e04792563e6a:/# git clone https://github.com/repo/id +root@e04792563e6a:/# inspect4py -i id +``` +2. Creating a [volume](https://docs.docker.com/storage/volumes/). For example, for mounting the $PWD folder: + +``` +docker run -it -v -v $PWD:/out --rm inspect4py:1.0 /bin/bash +# Docker image starts +root@e04792563e6a:/# inspect4py -i /out/path/to/repo +``` + +Other useful commands when using Docker: +``` +docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- +docker image rm -f inspect4py:1.0 +``` + +## Execution + +The tool can be executed to inspect a file, or all the files of a given directory (and its subdirectories). +For example, it can be used to inspect all the python files of a given GitHub repository (that has been previously cloned locally). + +The tool by default stores the results in the `OutputDir` directory, but users can specify their own directory name by using `-o` or `--output` flags. + + +``` +inspect4py --input_path [--output_dir "OutputDir", --ignore_dir_pattern "__", ignore_file_pattern "__" --requirements --html_output] +``` + +For clarity, we have added a `help` command to explain each input parameter: + +``` +inspect4py --help + + +Usage: inspect4py [OPTIONS] + +Options: + --version Show the version and exit. + -i, --input_path TEXT input path of the file or directory to + inspect. [required] + -o, --output_dir TEXT output directory path to store results. If + the directory does not exist, the tool will + create it. + -ignore_dir, --ignore_dir_pattern TEXT + ignore directories starting with a certain + pattern. This parameter can be provided + multiple times to ignore multiple directory + patterns. + -ignore_file, --ignore_file_pattern TEXT + ignore files starting with a certain + pattern. This parameter can be provided + multiple times to ignore multiple file + patterns. + -r, --requirements find the requirements of the repository. + -html, --html_output generates an html file of the DirJson in the + output directory. + -cl, --call_list generates the call list in a separate html + file. + -cf, --control_flow generates the call graph for each file in a + different directory. + -dt, --directory_tree captures the file directory tree from the + root path of the target repository. + -si, --software_invocation generates which are the software + invocation commands to run and test the + target repository. + -ast, -—abstract_syntax_tree generates abstract syntax tree in json format. + -sc, --source_code generates source code of each ast node. + -ld, --license_detection detects the license of the target repository. + -rm, --readme extract all readme files in the target repository. + -md, --metadata extract metadata of the target repository using + Github API. + -df, --data_flow extract data flow graph for every function, BOOL + -st, --symbol_table symbol table file location. STR + --help Show this message and exit. +``` + +## Documentation + +For additional documentation and examples, please have a look at our [online documentation](https://inspect4py.readthedocs.io/en/latest/) + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the development branch (`dev`)**. The master branch has only the code associated to the latest release. + +## Acknowledgements + +We would like to thank Laura Camacho, designer of the logo \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/inspect4py/README.md b/src/somef_core/test/test_data/repositories/inspect4py/README.md new file mode 100644 index 0000000..f872340 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/inspect4py/README.md @@ -0,0 +1,255 @@ +# inspect4py +[![PyPI](https://badge.fury.io/py/inspect4py.svg)](https://badge.fury.io/py/inspect4py) [![DOI](https://zenodo.org/badge/349160905.svg)](https://zenodo.org/badge/latestdoi/349160905) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) + +logo + +Library to allow users inspect a software project folder (i.e., a directory and its subdirectories) and extract all the most relevant information, such as class, method and parameter documentation, classes (and their methods), functions, etc. + +## Features: + +Given a folder with code, `inspect4py` will: + +- Extract all imported modules and how each module is imported as (i.e., whether they are internal or external). +- Extract all functions in the code, including their documentation, parameters, accepted values, and call list. +- Extract all classes in the code, with all their methods and respective documentation +- Extract the control flow of each file. +- Extract the hierarchy of directories and files. +- Extract the requirements used in the software project. +- Classify which files are tests +- Classify the main type of software project (script, package, library or service). Only one type is returned as main type (e.g., if a library has the option to be deployed as a service, `inspect4py` will return `Library` as its main type) +- Return a ranking of the different ways in which a a software component can be run, ordered by relevance. + + +All metadata is extracted as a JSON file. + + +Inspect4py currently works **only for Python 3 projects**. + +## Background: + +`inspect4py` added the functionality of capture [Data Flow Graphs](http://bears.ece.ucsb.edu/research-info/DP/dfg.html) for each function inspired by GraphCodeBERT: [Github](https://github.com/microsoft/CodeBERT) & [Paper](https://arxiv.org/abs/2009.08366). The illustration is given: +|Source Code|List Output|Networkx Image| +|:-:|:-:|:-:| +|
def max(a, b):
x = 0
if a > b:
x = a
else:
x = b
return x
|
('a', 3, 'comesFrom', [], [])
('b', 5, 'comesFrom', [], [])
('x', 8, 'computedFrom', ['0'], [10])
('0', 10, 'comesFrom', [], [])
('a', 12, 'comesFrom', ['a'], [3])
('b', 14, 'comesFrom', ['b'], [5])
('x', 16, 'computedFrom', ['a'], [18])
('a', 18, 'comesFrom', ['a'], [3])
('x', 21, 'computedFrom', ['b'], [23])
('b', 23, 'comesFrom', ['b'], [5])
('x', 25, 'comesFrom', ['x'], [16, 21])
|![image](docs/images/data_flow.png)| + +`inspect4py` uses [ASTs](https://en.wikipedia.org/wiki/Abstract_syntax_tree), more specifically +the [ast](https://docs.python.org/3/library/ast.html) module in Python, generating +a tree of objects (per file) whose classes all inherit from [ast.AST](https://docs.python.org/3/library/ast.html#ast.AST). + +`inspect4py` parses each of the input file(s) as an AST tree, extracting the relevant information and storing it as a JSON file. Furthermore, it also captures the control flow of each input file(s), by using another two libraries: + +- [staticfg](inspect4py/staticfg): StatiCFG is a package that can be used to produce control flow graphs (CFGs) for Python 3 programs. The CFGs it generates can be easily visualised with graphviz and used for static analysis. We have a flag in the code (FLAG_PNG) to indicate if we want to generate this type of control flow graphs or not. **Note**: The original code of this package can be found [here](https://github.com/coetaur0/staticfg), which has been fixed it in our [repository](inspect4py/staticfg) + +We also use [docstring_parser](https://pypi.org/project/docstring-parser/), which has support for ReST, Google, and Numpydoc-style docstrings. Some (basic) tests done using this library can be found at [here](./test_docstring_parser/). + +Finally, we reuse [Pigar](https://github.com/damnever/pigar) for generating automatically the requirements of a given repository. This is an optional funcionality. In order to activate the argument (`-r`) has to be indicated when running inspect4py. + +## Cite inspect4py +Please cite our MSR 2022 demo paper: +``` +@inproceedings{FilgueiraG22, + author = {Rosa Filgueira and + Daniel Garijo}, + title = {Inspect4py: {A} Knowledge Extraction Framework for Python Code Repositories}, + booktitle = {{IEEE/ACM} 19th International Conference on Mining Software Repositories, + {MSR} 2022, Pittsburgh, PA, USA, May 23-24, 2022}, + pages = {232--236}, + publisher = {{IEEE}}, + year = {2022}, + url = {https://dgarijo.com/papers/inspect4py_MSR2022.pdf}, + doi = {10.1145/3524842.3528497} +} +``` + +## Install + +### Preliminaries + +Make sure you have tree-sitter installed, C complier is needed, more [info](https://github.com/tree-sitter/tree-sitter): + +``` +pip install tree-sitter +``` +Note that if the ".so" file is not working properly, it is recommended that run the following commeds to generate a so file for your OS: +``` +git clone https://github.com/tree-sitter/tree-sitter-python + +python inspect4py/build.py +``` + +Make sure you have graphviz installed: + +``` +sudo apt-get install graphviz +``` + +### Python version +We have tested `inspect4py` in Python 3.7+. **Our recommended version is Python 3.9**. + + +### Operative System +We have tested `inspect4py` in Unix, MacOS and Windows 11(22621.1265). + +### Installation from pypi +`inspect4py` is [available in pypi!](https://pypi.org/project/inspect4py/) Just install it like a regular package: + +``` +pip install inspect4py +``` + +You are done! + +Then try to update the python-dev utilities: `sudo apt-get install python3.X-dev` (where X is your python version) + +### Installation from code + +Prepare a virtual Python3 enviroment, `cd` into the `inspect4py` folder and install the package as follows: + +``` +git clone https://github.com/SoftwareUnderstanding/inspect4py +cd inspect4py +pip install -e . +``` + +You are done! + +### Package dependencies: +``` +docstring_parser==0.7 +astor +graphviz +click +pigar +setuptools==54.2.0 +json2html +configparser +bigcode_astgen +GitPython +tree-sitter +``` + +If you want to run the evaluations, do not forget to add `pandas` to the previous set. + +### Installation through Docker + +You need to have [Docker](https://docs.docker.com/get-started/) installed. + +Next, clone the `inspect4py` repository: + +``` +git clone https://github.com/SoftwareUnderstanding/inspect4py/ +``` + +Generate a Docker image for `inspect4py`: + +``` +docker build --tag inspect4py:1.0 . +``` + +Run the `inspect4py` image: + +``` +docker run -it --rm inspect4py:1.0 /bin/bash +``` + +Now you can run `inspect4py`: +``` +root@e04792563e6a:/# inspect4py --help +``` + +For more information about `inspect4py` execution options, please see the section below (Execution). + +Note that when running `inspect4py` with Docker, you will need to need to provide a path to the target repository to analyze. You can do this by: + +1. Cloning the target repository. For example: + +``` +docker run -it --rm inspect4py:1.0 /bin/bash +# Docker image starts +root@e04792563e6a:/# git clone https://github.com/repo/id +root@e04792563e6a:/# inspect4py -i id +``` +2. Creating a [volume](https://docs.docker.com/storage/volumes/). For example, for mounting the $PWD folder: + +``` +docker run -it -v -v $PWD:/out --rm inspect4py:1.0 /bin/bash +# Docker image starts +root@e04792563e6a:/# inspect4py -i /out/path/to/repo +``` + +Other useful commands when using Docker: +``` +docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- +docker image rm -f inspect4py:1.0 +``` + +## Execution + +The tool can be executed to inspect a file, or all the files of a given directory (and its subdirectories). +For example, it can be used to inspect all the python files of a given GitHub repository (that has been previously cloned locally). + +The tool by default stores the results in the `OutputDir` directory, but users can specify their own directory name by using `-o` or `--output` flags. + + +``` +inspect4py --input_path [--output_dir "OutputDir", --ignore_dir_pattern "__", ignore_file_pattern "__" --requirements --html_output] +``` + +For clarity, we have added a `help` command to explain each input parameter: + +``` +inspect4py --help + + +Usage: inspect4py [OPTIONS] + +Options: + --version Show the version and exit. + -i, --input_path TEXT input path of the file or directory to + inspect. [required] + -o, --output_dir TEXT output directory path to store results. If + the directory does not exist, the tool will + create it. + -ignore_dir, --ignore_dir_pattern TEXT + ignore directories starting with a certain + pattern. This parameter can be provided + multiple times to ignore multiple directory + patterns. + -ignore_file, --ignore_file_pattern TEXT + ignore files starting with a certain + pattern. This parameter can be provided + multiple times to ignore multiple file + patterns. + -r, --requirements find the requirements of the repository. + -html, --html_output generates an html file of the DirJson in the + output directory. + -cl, --call_list generates the call list in a separate html + file. + -cf, --control_flow generates the call graph for each file in a + different directory. + -dt, --directory_tree captures the file directory tree from the + root path of the target repository. + -si, --software_invocation generates which are the software + invocation commands to run and test the + target repository. + -ast, -—abstract_syntax_tree generates abstract syntax tree in json format. + -sc, --source_code generates source code of each ast node. + -ld, --license_detection detects the license of the target repository. + -rm, --readme extract all readme files in the target repository. + -md, --metadata extract metadata of the target repository using + Github API. + -df, --data_flow extract data flow graph for every function, BOOL + -st, --symbol_table symbol table file location. STR + --help Show this message and exit. +``` + +## Documentation + +For additional documentation and examples, please have a look at our [online documentation](https://inspect4py.readthedocs.io/en/latest/) + +## Contribution guidelines +Contributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the development branch (`dev`)**. The master branch has only the code associated to the latest release. + +## Acknowledgements + +We would like to thank Laura Camacho, designer of the logo \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/js-template/bower.json b/src/somef_core/test/test_data/repositories/js-template/bower.json new file mode 100644 index 0000000..0f0d4a5 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/js-template/bower.json @@ -0,0 +1,26 @@ +{ + "name": "alarm", + "description": "Alarm clock project during week1 day2 JS at Epicodus.", + "main": "gulpfile.js", + "authors": [ + "Andrew Accuardi ", + "Another Author " + ], + "license": "ISC", + "homepage": "", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "jquery": "^3.1.1", + "bootstrap": "^3.3.7", + "moment": "^2.17.1", + "components-font-awesome": "^4.7.0", + "font-awesome": "^4.7.0", + "materialize": "^0.97.8" + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/js-template/package.json b/src/somef_core/test/test_data/repositories/js-template/package.json new file mode 100644 index 0000000..5cdbe94 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/js-template/package.json @@ -0,0 +1,25 @@ +{ + "name": "alarm", + "version": "1.0.0", + "description": "Alarm clock project during week1 day2 JS at Epicodus.", + "main": "gulpfile.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "gulp": "^3.9.1", + "bower-files": "^3.14.1", + "browser-sync": "^2.18.5", + "browserfy": "^1.0.0", + "browserify": "^13.1.1", + "del": "^2.2.2", + "gulp-concat": "^2.6.1", + "gulp-jshint": "^2.0.4", + "gulp-uglify": "^2.0.0", + "gulp-util": "^3.0.8", + "jshint": "^2.9.4", + "vinyl-source-stream": "^1.1.0" + } +} diff --git a/src/somef_core/test/test_data/repositories/maven/pom 2.xml b/src/somef_core/test/test_data/repositories/maven/pom 2.xml new file mode 100644 index 0000000..b92fb4e --- /dev/null +++ b/src/somef_core/test/test_data/repositories/maven/pom 2.xml @@ -0,0 +1,1275 @@ + + + + 4.0.0 + + + org.apache.maven + maven-parent + 45 + + + + maven + 4.1.0-SNAPSHOT + pom + + Apache Maven + Maven is a software build management and + comprehension tool. Based on the concept of a project object model: + builds, dependency management, documentation creation, site + publication, and distribution publication are all controlled from + the declarative file. Maven can be extended by plugins to utilise a + number of other development tools for reporting or the build + process. + https://maven.apache.org/ref/${project.version}/ + 2001 + + + + Stuart McCulloch + + + Christian Schulte (MNG-2199) + + + Christopher Tubbs (MNG-4226) + + + Konstantin Perikov (MNG-4565) + + + Sébastian Le Merdy (MNG-5613) + + + Mark Ingram (MNG-5639) + + + Phil Pratt-Szeliga (MNG-5645) + + + Florencia Tarditti (PR 41) + + + Anton Tanasenko + + + Joseph Walton (MNG-5297) + + + Fabiano Cipriano de Oliveira (MNG-6261) + + + Mike Mol (MNG-6665) + + + Martin Kanters + JPoint + + + Maarten Mulders + Info Support + + + Luc Klaassen (MNG-6065) + + + Wouter Aarts (MNG-6065) + + + Arturo Bernal + + + + + api + impl + compat + apache-maven + + + + scm:git:https://gitbox.apache.org/repos/asf/maven.git + scm:git:https://gitbox.apache.org/repos/asf/maven.git + maven-4.0.0-rc-1 + https://github.com/apache/maven/tree/${project.scm.tag} + + + GitHub Issues + https://github.com/apache/maven/issues + + + Jenkins + https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven/ + + + + apache.website + scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path} + + https://maven.apache.org/download.html + + + + 17 + ${javaVersion} + ${javaVersion} + ${javaVersion} + full + true + 3.9.8 + + apache-maven + Maven + Apache Maven + ref/4-LATEST + 2025-06-24T20:18:00Z + + 9.9 + 1.17.8 + 2.9.0 + 1.10.0 + 5.1.0 + 33.5.0-jre + 1.0.1 + + 2.0.1 + 1.3.2 + 3.30.6 + 1.37 + 6.0.1 + 1.4.0 + 1.5.21 + 5.20.0 + 1.5.1 + 1.29 + 2.0.1 + 4.1.0 + 2.0.13 + 4.1.0 + 0.9.0.M4 + 2.0.17 + 4.2.2 + 3.5.3 + 7.1.1 + 2.11.0 + + + 3.0.0 + 2.80.0 + + + 0.14.1 + + + + + + + + + + org.apache.maven + maven-artifact + ${project.version} + + + org.apache.maven + maven-builder-support + ${project.version} + + + org.apache.maven + maven-jline + ${project.version} + + + org.apache.maven + maven-logging + ${project.version} + + + org.apache.maven + maven-core + ${project.version} + + + org.apache.maven + maven-impl + ${project.version} + + + org.apache.maven + maven-embedder + ${project.version} + + + org.apache.maven + maven-cli + ${project.version} + + + org.apache.maven + maven-model + ${project.version} + + + org.apache.maven + maven-api-core + ${project.version} + + + org.apache.maven + maven-api-annotations + ${project.version} + + + org.apache.maven + maven-api-model + ${project.version} + + + org.apache.maven + maven-api-settings + ${project.version} + + + org.apache.maven + maven-api-spi + ${project.version} + + + org.apache.maven + maven-api-toolchain + ${project.version} + + + org.apache.maven + maven-api-plugin + ${project.version} + + + org.apache.maven + maven-api-xml + ${project.version} + + + org.apache.maven + maven-api-di + ${project.version} + + + org.apache.maven + maven-api-metadata + ${project.version} + + + org.apache.maven + maven-api-cli + ${project.version} + + + org.apache.maven + maven-di + ${project.version} + + + org.apache.maven + maven-support + ${project.version} + + + org.apache.maven + maven-model-builder + ${project.version} + + + org.apache.maven + maven-plugin-api + ${project.version} + + + org.apache.maven + maven-repository-metadata + ${project.version} + + + org.apache.maven + maven-resolver-provider + ${project.version} + + + org.apache.maven + maven-settings + ${project.version} + + + org.apache.maven + maven-settings-builder + ${project.version} + + + org.apache.maven + maven-toolchain-model + ${project.version} + + + org.apache.maven + maven-toolchain-builder + ${project.version} + + + org.apache.maven + maven-xml + ${project.version} + + + org.apache.maven + maven-compat + ${project.version} + + + + org.codehaus.plexus + plexus-xml + ${plexusXmlVersion} + + + com.google.inject + guice + ${guiceVersion} + classes + + + com.google.guava + guava + ${guavaVersion} + + + com.google.code.findbugs + jsr305 + + + com.google.errorprone + error_prone_annotations + + + com.google.guava + listenablefuture + + + com.google.j2objc + j2objc-annotations + + + org.checkerframework + checker-qual + + + + + org.eclipse.sisu + org.eclipse.sisu.plexus + ${sisuVersion} + + + + + + org.eclipse.sisu + org.eclipse.sisu.inject + + + org.apache.maven + maven-xml-impl + + + + + javax.annotation + javax.annotation-api + ${javaxAnnotationApiVersion} + + + org.eclipse.sisu + org.eclipse.sisu.inject + ${sisuVersion} + + + org.ow2.asm + asm + ${asmVersion} + + + javax.inject + javax.inject + 1 + + + org.codehaus.plexus + plexus-classworlds + ${classWorldsVersion} + + + org.codehaus.plexus + plexus-interpolation + ${plexusInterpolationVersion} + + + org.codehaus.plexus + plexus-interactivity-api + ${plexusInteractivityVersion} + + + org.jline + jline-reader + ${jlineVersion} + + + org.jline + jline-style + ${jlineVersion} + + + org.jline + jline-builtins + ${jlineVersion} + + + org.jline + jline-console + ${jlineVersion} + + + org.jline + jline-console-ui + ${jlineVersion} + + + org.jline + jline-terminal + ${jlineVersion} + + + org.jline + jline-terminal-ffm + ${jlineVersion} + + + org.jline + jline-terminal-jni + ${jlineVersion} + + + org.jline + jline-native + ${jlineVersion} + + + org.jline + jansi-core + ${jlineVersion} + + + org.slf4j + slf4j-api + ${slf4jVersion} + + + org.slf4j + slf4j-simple + ${slf4jVersion} + true + + + ch.qos.logback + logback-classic + ${logbackClassicVersion} + true + + + + org.apache.maven.wagon + wagon-provider-api + ${wagonVersion} + + + org.apache.maven.wagon + wagon-file + ${wagonVersion} + + + org.apache.maven.wagon + wagon-http + ${wagonVersion} + + + + org.apache.maven.resolver + maven-resolver-api + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-spi + ${resolverVersion} + + + com.google.errorprone + error_prone_annotations + + + + + org.apache.maven.resolver + maven-resolver-impl + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-util + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-named-locks + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-connector-basic + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-file + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-apache + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-jdk + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-wagon + ${resolverVersion} + + + + commons-cli + commons-cli + ${commonsCliVersion} + + + commons-jxpath + commons-jxpath + ${jxpathVersion} + + + org.codehaus.plexus + plexus-sec-dispatcher + ${securityDispatcherVersion} + + + com.fasterxml.woodstox + woodstox-core + ${woodstoxVersion} + + + org.codehaus.woodstox + stax2-api + ${stax2ApiVersion} + + + + org.xmlunit + xmlunit-core + ${xmlunitVersion} + test + + + org.xmlunit + xmlunit-matchers + ${xmlunitVersion} + test + + + org.hamcrest + hamcrest-core + + + + + + org.codehaus.plexus + plexus-testing + ${plexusTestingVersion} + test + + + com.google.inject + guice + + + + + org.junit + junit-bom + ${junitVersion} + pom + import + + + org.mockito + mockito-bom + ${mockitoVersion} + pom + import + + + net.bytebuddy + byte-buddy + ${byteBuddyVersion} + + + com.google.jimfs + jimfs + 1.3.1 + + + org.jdom + jdom2 + 2.0.6.1 + + + org.openjdk.jmh + jmh-core + ${jmhVersion} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmhVersion} + + + eu.maveniverse.maven.mimir + testing + 0.10.4 + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + -Xmx256m @{jacocoArgLine} + + ${toolboxVersion} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + -Xmx256m @{jacocoArgLine} + + ${toolboxVersion} + + + + + + com.github.siom79.japicmp + japicmp-maven-plugin + 0.24.2 + + + + cmp + + verify + + + + ${maven.baseline} + true + true + + true + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.1 + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.codehaus.mojo + buildnumber-maven-plugin + 3.2.1 + + + org.apache.maven.plugins + maven-source-plugin + + + false + true + + + + org.jacoco + jacoco-maven-plugin + 0.8.14 + + + **/org/apache/maven/it/** + **/org/apache/maven/its/** + **/org/apache/maven/coreit/** + **/org/apache/maven/plugin/coreit/** + **/org/apache/maven/wagon/providers/coreit/** + **/org/apache/maven/coreits/** + + + + + org.apache.maven.plugins + maven-pmd-plugin + + + net.sourceforge.pmd + pmd-core + 7.18.0 + + + + + org.eclipse.sisu + sisu-maven-plugin + ${sisuVersion} + + + org.ow2.asm + asm + ${asmVersion} + + + + + + + + io.github.olamy.maven.plugins + jacoco-aggregator-maven-plugin + 1.0.4 + + + org.apache.maven.plugins + maven-doap-plugin + 1.2 + + + The mission of the Apache Maven project is to create and maintain software + libraries that provide a widely-used project build tool, targeting mainly Java + development. Apache Maven promotes the use of dependencies via a + standardized coordinates system, binary plugins, and a standard build + lifecycle. + + + + + org.apache.rat + apache-rat-plugin + + + rat-check + false + + + Jenkinsfile + **/.gitattributes + src/test/resources*/** + src/test/projects/** + src/test/remote-repo/** + its/** + **/*.odg + **/*.svg + .asf.yaml + .mvn/** + .jbang/** + + src/main/appended-resources/licenses/EPL-1.0.txt + src/main/appended-resources/licenses/unrecognized-aopalliance-1.0.txt + src/main/appended-resources/licenses/unrecognized-javax.annotation-api-1.3.2.txt + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + ensure-no-guice-with-asm + + enforce + + validate + + + + + + com.google.inject:guice:* + + + com.google.inject:guice:*:jar:*:classes + + use guice without asm shaded in. + + + true + + + + ensure-no-sonatype-cipher-and-sec-dispatcher + + enforce + + validate + + + + + org.sonatype.plexus:plexus-sec-dispatcher + org.sonatype.plexus:plexus-cipher + + ensure no more org.sonatype.plexus:plexus-cipher and org.sonatype.plexus:plexus-sec-dispatcher. + + + true + + + + enforce-bytecode-version + + enforce + + + + + [17,) + + + ${maven.compiler.release} + + test + + + org.jline:jline-terminal-ffm + + + + true + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + prepare-for-mockito-agent + + properties + + + + + + com.diffplug.spotless + spotless-maven-plugin + + + + + + + mockito + + + org.mockito:mockito-core:jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xmx256m -javaagent:${org.mockito:mockito-core:jar} + + + + + + + + graph + + + !windows + + + + + + org.fusesource.mvnplugins + maven-graph-plugin + 1.45 + false + + + graph + + reactor + + pre-site + + true + true + test + true + true + ${project.build.directory}/graph/reactor-graph.dot + + + + + + dev.jbang + jbang-maven-plugin + 0.0.8 + false + + + graph + + run + + pre-site + + + + --verbose + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + false + + + + run + + pre-site + + + + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.6.2 + false + + + org.apache.maven.resolver + maven-resolver-tools + ${resolverVersion} + + + + + render-configuration-page + + java + + pre-site + + + ${project.basedir}/src/configuration-templates + + true + org.eclipse.aether.tools.CollectConfiguration + + --mode=maven + + --templates=maven-configuration.md + ${project.basedir} + ${project.build.directory}/generated-site/markdown + + + + + render-configuration-properties + + java + + pre-site + + + ${project.basedir}/src/configuration-templates + + true + org.eclipse.aether.tools.CollectConfiguration + + --mode=maven + + --templates=configuration.properties,configuration.yaml + ${project.basedir} + ${project.build.directory}/generated-site/resources + + + + + + + + + + apache-release + + + + org.apache.maven.plugins + maven-assembly-plugin + + + source-release-assembly + + + true + + + + + + + + + reporting + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + provisional + tf + Provisional: + + + + + Maven 4 API - Core + org.apache.maven.api* + + + Maven 4 API - Plugin + org.apache.maven.api.plugin.descriptor* + + + Maven 4 API - Model + org.apache.maven.api.model + + + Maven 4 API - Settings + org.apache.maven.api.settings + + + Maven 4 API - Toolchain + org.apache.maven.api.toolchain + + + Maven 4 API - Meta + org.apache.maven.api.annotations + + + Maven 4 API - DI + org.apache.maven.api.di + + + Maven 4 API - Metadata + org.apache.maven.api.metadata + + + Maven 4 API - SPI + org.apache.maven.api.spi + + + Maven 4 API - XML + org.apache.maven.api.xml + + + + + + aggregate + + aggregate + + false + + + + + org.apache.maven.plugins + maven-jxr-plugin + + + aggregate + + aggregate + + false + + + + + + + + run-its + + its + + + + ci + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${project.build.directory}/test-results-surefire + + + + + + + + jacoco + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xmx1G @{jacocoArgLine} + ${project.build.directory}/test-results-surefire + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-initialize + + prepare-agent + + initialize + + jacocoArgLine + + + + jacoco-site + + report + + package + + + **/org/apache/maven/** + + + + + + + + + + \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/maven/pom.xml b/src/somef_core/test/test_data/repositories/maven/pom.xml new file mode 100644 index 0000000..b92fb4e --- /dev/null +++ b/src/somef_core/test/test_data/repositories/maven/pom.xml @@ -0,0 +1,1275 @@ + + + + 4.0.0 + + + org.apache.maven + maven-parent + 45 + + + + maven + 4.1.0-SNAPSHOT + pom + + Apache Maven + Maven is a software build management and + comprehension tool. Based on the concept of a project object model: + builds, dependency management, documentation creation, site + publication, and distribution publication are all controlled from + the declarative file. Maven can be extended by plugins to utilise a + number of other development tools for reporting or the build + process. + https://maven.apache.org/ref/${project.version}/ + 2001 + + + + Stuart McCulloch + + + Christian Schulte (MNG-2199) + + + Christopher Tubbs (MNG-4226) + + + Konstantin Perikov (MNG-4565) + + + Sébastian Le Merdy (MNG-5613) + + + Mark Ingram (MNG-5639) + + + Phil Pratt-Szeliga (MNG-5645) + + + Florencia Tarditti (PR 41) + + + Anton Tanasenko + + + Joseph Walton (MNG-5297) + + + Fabiano Cipriano de Oliveira (MNG-6261) + + + Mike Mol (MNG-6665) + + + Martin Kanters + JPoint + + + Maarten Mulders + Info Support + + + Luc Klaassen (MNG-6065) + + + Wouter Aarts (MNG-6065) + + + Arturo Bernal + + + + + api + impl + compat + apache-maven + + + + scm:git:https://gitbox.apache.org/repos/asf/maven.git + scm:git:https://gitbox.apache.org/repos/asf/maven.git + maven-4.0.0-rc-1 + https://github.com/apache/maven/tree/${project.scm.tag} + + + GitHub Issues + https://github.com/apache/maven/issues + + + Jenkins + https://ci-maven.apache.org/job/Maven/job/maven-box/job/maven/ + + + + apache.website + scm:svn:https://svn.apache.org/repos/asf/maven/website/components/${maven.site.path} + + https://maven.apache.org/download.html + + + + 17 + ${javaVersion} + ${javaVersion} + ${javaVersion} + full + true + 3.9.8 + + apache-maven + Maven + Apache Maven + ref/4-LATEST + 2025-06-24T20:18:00Z + + 9.9 + 1.17.8 + 2.9.0 + 1.10.0 + 5.1.0 + 33.5.0-jre + 1.0.1 + + 2.0.1 + 1.3.2 + 3.30.6 + 1.37 + 6.0.1 + 1.4.0 + 1.5.21 + 5.20.0 + 1.5.1 + 1.29 + 2.0.1 + 4.1.0 + 2.0.13 + 4.1.0 + 0.9.0.M4 + 2.0.17 + 4.2.2 + 3.5.3 + 7.1.1 + 2.11.0 + + + 3.0.0 + 2.80.0 + + + 0.14.1 + + + + + + + + + + org.apache.maven + maven-artifact + ${project.version} + + + org.apache.maven + maven-builder-support + ${project.version} + + + org.apache.maven + maven-jline + ${project.version} + + + org.apache.maven + maven-logging + ${project.version} + + + org.apache.maven + maven-core + ${project.version} + + + org.apache.maven + maven-impl + ${project.version} + + + org.apache.maven + maven-embedder + ${project.version} + + + org.apache.maven + maven-cli + ${project.version} + + + org.apache.maven + maven-model + ${project.version} + + + org.apache.maven + maven-api-core + ${project.version} + + + org.apache.maven + maven-api-annotations + ${project.version} + + + org.apache.maven + maven-api-model + ${project.version} + + + org.apache.maven + maven-api-settings + ${project.version} + + + org.apache.maven + maven-api-spi + ${project.version} + + + org.apache.maven + maven-api-toolchain + ${project.version} + + + org.apache.maven + maven-api-plugin + ${project.version} + + + org.apache.maven + maven-api-xml + ${project.version} + + + org.apache.maven + maven-api-di + ${project.version} + + + org.apache.maven + maven-api-metadata + ${project.version} + + + org.apache.maven + maven-api-cli + ${project.version} + + + org.apache.maven + maven-di + ${project.version} + + + org.apache.maven + maven-support + ${project.version} + + + org.apache.maven + maven-model-builder + ${project.version} + + + org.apache.maven + maven-plugin-api + ${project.version} + + + org.apache.maven + maven-repository-metadata + ${project.version} + + + org.apache.maven + maven-resolver-provider + ${project.version} + + + org.apache.maven + maven-settings + ${project.version} + + + org.apache.maven + maven-settings-builder + ${project.version} + + + org.apache.maven + maven-toolchain-model + ${project.version} + + + org.apache.maven + maven-toolchain-builder + ${project.version} + + + org.apache.maven + maven-xml + ${project.version} + + + org.apache.maven + maven-compat + ${project.version} + + + + org.codehaus.plexus + plexus-xml + ${plexusXmlVersion} + + + com.google.inject + guice + ${guiceVersion} + classes + + + com.google.guava + guava + ${guavaVersion} + + + com.google.code.findbugs + jsr305 + + + com.google.errorprone + error_prone_annotations + + + com.google.guava + listenablefuture + + + com.google.j2objc + j2objc-annotations + + + org.checkerframework + checker-qual + + + + + org.eclipse.sisu + org.eclipse.sisu.plexus + ${sisuVersion} + + + + + + org.eclipse.sisu + org.eclipse.sisu.inject + + + org.apache.maven + maven-xml-impl + + + + + javax.annotation + javax.annotation-api + ${javaxAnnotationApiVersion} + + + org.eclipse.sisu + org.eclipse.sisu.inject + ${sisuVersion} + + + org.ow2.asm + asm + ${asmVersion} + + + javax.inject + javax.inject + 1 + + + org.codehaus.plexus + plexus-classworlds + ${classWorldsVersion} + + + org.codehaus.plexus + plexus-interpolation + ${plexusInterpolationVersion} + + + org.codehaus.plexus + plexus-interactivity-api + ${plexusInteractivityVersion} + + + org.jline + jline-reader + ${jlineVersion} + + + org.jline + jline-style + ${jlineVersion} + + + org.jline + jline-builtins + ${jlineVersion} + + + org.jline + jline-console + ${jlineVersion} + + + org.jline + jline-console-ui + ${jlineVersion} + + + org.jline + jline-terminal + ${jlineVersion} + + + org.jline + jline-terminal-ffm + ${jlineVersion} + + + org.jline + jline-terminal-jni + ${jlineVersion} + + + org.jline + jline-native + ${jlineVersion} + + + org.jline + jansi-core + ${jlineVersion} + + + org.slf4j + slf4j-api + ${slf4jVersion} + + + org.slf4j + slf4j-simple + ${slf4jVersion} + true + + + ch.qos.logback + logback-classic + ${logbackClassicVersion} + true + + + + org.apache.maven.wagon + wagon-provider-api + ${wagonVersion} + + + org.apache.maven.wagon + wagon-file + ${wagonVersion} + + + org.apache.maven.wagon + wagon-http + ${wagonVersion} + + + + org.apache.maven.resolver + maven-resolver-api + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-spi + ${resolverVersion} + + + com.google.errorprone + error_prone_annotations + + + + + org.apache.maven.resolver + maven-resolver-impl + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-util + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-named-locks + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-connector-basic + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-file + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-apache + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-jdk + ${resolverVersion} + + + org.apache.maven.resolver + maven-resolver-transport-wagon + ${resolverVersion} + + + + commons-cli + commons-cli + ${commonsCliVersion} + + + commons-jxpath + commons-jxpath + ${jxpathVersion} + + + org.codehaus.plexus + plexus-sec-dispatcher + ${securityDispatcherVersion} + + + com.fasterxml.woodstox + woodstox-core + ${woodstoxVersion} + + + org.codehaus.woodstox + stax2-api + ${stax2ApiVersion} + + + + org.xmlunit + xmlunit-core + ${xmlunitVersion} + test + + + org.xmlunit + xmlunit-matchers + ${xmlunitVersion} + test + + + org.hamcrest + hamcrest-core + + + + + + org.codehaus.plexus + plexus-testing + ${plexusTestingVersion} + test + + + com.google.inject + guice + + + + + org.junit + junit-bom + ${junitVersion} + pom + import + + + org.mockito + mockito-bom + ${mockitoVersion} + pom + import + + + net.bytebuddy + byte-buddy + ${byteBuddyVersion} + + + com.google.jimfs + jimfs + 1.3.1 + + + org.jdom + jdom2 + 2.0.6.1 + + + org.openjdk.jmh + jmh-core + ${jmhVersion} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmhVersion} + + + eu.maveniverse.maven.mimir + testing + 0.10.4 + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + -Xmx256m @{jacocoArgLine} + + ${toolboxVersion} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + -Xmx256m @{jacocoArgLine} + + ${toolboxVersion} + + + + + + com.github.siom79.japicmp + japicmp-maven-plugin + 0.24.2 + + + + cmp + + verify + + + + ${maven.baseline} + true + true + + true + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.1 + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.codehaus.mojo + buildnumber-maven-plugin + 3.2.1 + + + org.apache.maven.plugins + maven-source-plugin + + + false + true + + + + org.jacoco + jacoco-maven-plugin + 0.8.14 + + + **/org/apache/maven/it/** + **/org/apache/maven/its/** + **/org/apache/maven/coreit/** + **/org/apache/maven/plugin/coreit/** + **/org/apache/maven/wagon/providers/coreit/** + **/org/apache/maven/coreits/** + + + + + org.apache.maven.plugins + maven-pmd-plugin + + + net.sourceforge.pmd + pmd-core + 7.18.0 + + + + + org.eclipse.sisu + sisu-maven-plugin + ${sisuVersion} + + + org.ow2.asm + asm + ${asmVersion} + + + + + + + + io.github.olamy.maven.plugins + jacoco-aggregator-maven-plugin + 1.0.4 + + + org.apache.maven.plugins + maven-doap-plugin + 1.2 + + + The mission of the Apache Maven project is to create and maintain software + libraries that provide a widely-used project build tool, targeting mainly Java + development. Apache Maven promotes the use of dependencies via a + standardized coordinates system, binary plugins, and a standard build + lifecycle. + + + + + org.apache.rat + apache-rat-plugin + + + rat-check + false + + + Jenkinsfile + **/.gitattributes + src/test/resources*/** + src/test/projects/** + src/test/remote-repo/** + its/** + **/*.odg + **/*.svg + .asf.yaml + .mvn/** + .jbang/** + + src/main/appended-resources/licenses/EPL-1.0.txt + src/main/appended-resources/licenses/unrecognized-aopalliance-1.0.txt + src/main/appended-resources/licenses/unrecognized-javax.annotation-api-1.3.2.txt + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + ensure-no-guice-with-asm + + enforce + + validate + + + + + + com.google.inject:guice:* + + + com.google.inject:guice:*:jar:*:classes + + use guice without asm shaded in. + + + true + + + + ensure-no-sonatype-cipher-and-sec-dispatcher + + enforce + + validate + + + + + org.sonatype.plexus:plexus-sec-dispatcher + org.sonatype.plexus:plexus-cipher + + ensure no more org.sonatype.plexus:plexus-cipher and org.sonatype.plexus:plexus-sec-dispatcher. + + + true + + + + enforce-bytecode-version + + enforce + + + + + [17,) + + + ${maven.compiler.release} + + test + + + org.jline:jline-terminal-ffm + + + + true + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + prepare-for-mockito-agent + + properties + + + + + + com.diffplug.spotless + spotless-maven-plugin + + + + + + + mockito + + + org.mockito:mockito-core:jar + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xmx256m -javaagent:${org.mockito:mockito-core:jar} + + + + + + + + graph + + + !windows + + + + + + org.fusesource.mvnplugins + maven-graph-plugin + 1.45 + false + + + graph + + reactor + + pre-site + + true + true + test + true + true + ${project.build.directory}/graph/reactor-graph.dot + + + + + + dev.jbang + jbang-maven-plugin + 0.0.8 + false + + + graph + + run + + pre-site + + + + --verbose + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + false + + + + run + + pre-site + + + + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.6.2 + false + + + org.apache.maven.resolver + maven-resolver-tools + ${resolverVersion} + + + + + render-configuration-page + + java + + pre-site + + + ${project.basedir}/src/configuration-templates + + true + org.eclipse.aether.tools.CollectConfiguration + + --mode=maven + + --templates=maven-configuration.md + ${project.basedir} + ${project.build.directory}/generated-site/markdown + + + + + render-configuration-properties + + java + + pre-site + + + ${project.basedir}/src/configuration-templates + + true + org.eclipse.aether.tools.CollectConfiguration + + --mode=maven + + --templates=configuration.properties,configuration.yaml + ${project.basedir} + ${project.build.directory}/generated-site/resources + + + + + + + + + + apache-release + + + + org.apache.maven.plugins + maven-assembly-plugin + + + source-release-assembly + + + true + + + + + + + + + reporting + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + provisional + tf + Provisional: + + + + + Maven 4 API - Core + org.apache.maven.api* + + + Maven 4 API - Plugin + org.apache.maven.api.plugin.descriptor* + + + Maven 4 API - Model + org.apache.maven.api.model + + + Maven 4 API - Settings + org.apache.maven.api.settings + + + Maven 4 API - Toolchain + org.apache.maven.api.toolchain + + + Maven 4 API - Meta + org.apache.maven.api.annotations + + + Maven 4 API - DI + org.apache.maven.api.di + + + Maven 4 API - Metadata + org.apache.maven.api.metadata + + + Maven 4 API - SPI + org.apache.maven.api.spi + + + Maven 4 API - XML + org.apache.maven.api.xml + + + + + + aggregate + + aggregate + + false + + + + + org.apache.maven.plugins + maven-jxr-plugin + + + aggregate + + aggregate + + false + + + + + + + + run-its + + its + + + + ci + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${project.build.directory}/test-results-surefire + + + + + + + + jacoco + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xmx1G @{jacocoArgLine} + ${project.build.directory}/test-results-surefire + + + + org.jacoco + jacoco-maven-plugin + + + jacoco-initialize + + prepare-agent + + initialize + + jacocoArgLine + + + + jacoco-site + + report + + package + + + **/org/apache/maven/** + + + + + + + + + + \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/maykinMedia/publiccode 2.yaml b/src/somef_core/test/test_data/repositories/maykinMedia/publiccode 2.yaml new file mode 100644 index 0000000..c829373 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/maykinMedia/publiccode 2.yaml @@ -0,0 +1,112 @@ +# This repository adheres to the publiccode.yml standard by including this +# metadata file that makes public software easily discoverable. +# More info at https://github.com/italia/publiccode.yml + +publiccodeYmlVersion: '0.2' + +name: Objects API +url: 'http://github.com/maykinmedia/objects-api.git' +softwareType: standalone/backend +softwareVersion: 3.5.0 +releaseDate: '2025-12-01' +logo: 'https://github.com/maykinmedia/objects-api/blob/master/docs/logo.png' +platforms: + - web + - linux + - windows + - mac + +categories: + - data-collection + - it-development + +developmentStatus: beta + +description: + nl: + shortDescription: API voor het beheren van objecten + documentation: 'https://objects-and-objecttypes-api.readthedocs.io/' + apiDocumentation: 'https://raw.githubusercontent.com/maykinmedia/objects-api/master/src/objects/api/v1/openapi.yaml' + features: + - Objecten API + - Minimalistische objecten beheerinterface + genericName: API component + longDescription: > + De **Objecten API** heeft als doel om uiteenlopende objecten eenvoudig te kunnen + registreren en ontsluiten in een gestandaardiseerd formaat. De Objecten API kan + door elke organisatie ingezet worden om de voor haar interessante objecten te + beheren. Ook kan een organisatie er voor kiezen een Objecten API in te zetten + voor Open Data, waarbij de geregistreerde objecten publiekelijk toegankelijk + zijn. + + Om het formaat van objecten, de zogenoemde objecttypen, vast te leggen wordt + gebruik gemaakt van de landelijke en/of een lokale `Objecttypen API`_. + + en: + shortDescription: API to manage objects + documentation: 'https://objects-and-objecttypes-api.readthedocs.io/' + apiDocumentation: 'https://raw.githubusercontent.com/maykinmedia/objects-api/master/src/objects/api/v1/openapi.yaml' + features: + - Objects API + - Minimalistic object management interface + genericName: API component + longDescription: > + The **Objects API** aims to easily store various objects and make them available in + standardized format. The Objects API can be used by any organization to manage + relevant objects. An organization can also choose to use the Objects API to + expose objects to the public, as Open Data. + + To define the format of objects, so called object types, organizations can use + a national and/or local `Objecttypes API`_. + +legal: + license: EUPL-1.2 + mainCopyrightOwner: Maykin Media + repoOwner: Maykin Media + +dependsOn: + open: + - name: Objecttypes API + optional: false + versionMin: '1.0' + - name: PostgreSQL + optional: false + versionMin: '14.0' + - name: PostGIS + optional: false + versionMin: '3.2' + - name: Kubernetes + optional: true + versionMin: '1.12' + - name: Docker + optional: true + versionMin: '18.0' + +inputTypes: + - application/json + +outputTypes: + - application/json + - text/html + +intendedAudience: + countries: + - nl + scope: + - government + +localisation: + availableLanguages: + - nl + - en + localisationReady: false + +maintenance: + type: contract + contractors: + - name: Maykin Media + email: info@maykinmedia.nl + website: https://www.maykinmedia.nl/ + contacts: + - name: Joeri Bekker + affiliation: Maykin Media \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/maykinMedia/publiccode.yaml b/src/somef_core/test/test_data/repositories/maykinMedia/publiccode.yaml new file mode 100644 index 0000000..c829373 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/maykinMedia/publiccode.yaml @@ -0,0 +1,112 @@ +# This repository adheres to the publiccode.yml standard by including this +# metadata file that makes public software easily discoverable. +# More info at https://github.com/italia/publiccode.yml + +publiccodeYmlVersion: '0.2' + +name: Objects API +url: 'http://github.com/maykinmedia/objects-api.git' +softwareType: standalone/backend +softwareVersion: 3.5.0 +releaseDate: '2025-12-01' +logo: 'https://github.com/maykinmedia/objects-api/blob/master/docs/logo.png' +platforms: + - web + - linux + - windows + - mac + +categories: + - data-collection + - it-development + +developmentStatus: beta + +description: + nl: + shortDescription: API voor het beheren van objecten + documentation: 'https://objects-and-objecttypes-api.readthedocs.io/' + apiDocumentation: 'https://raw.githubusercontent.com/maykinmedia/objects-api/master/src/objects/api/v1/openapi.yaml' + features: + - Objecten API + - Minimalistische objecten beheerinterface + genericName: API component + longDescription: > + De **Objecten API** heeft als doel om uiteenlopende objecten eenvoudig te kunnen + registreren en ontsluiten in een gestandaardiseerd formaat. De Objecten API kan + door elke organisatie ingezet worden om de voor haar interessante objecten te + beheren. Ook kan een organisatie er voor kiezen een Objecten API in te zetten + voor Open Data, waarbij de geregistreerde objecten publiekelijk toegankelijk + zijn. + + Om het formaat van objecten, de zogenoemde objecttypen, vast te leggen wordt + gebruik gemaakt van de landelijke en/of een lokale `Objecttypen API`_. + + en: + shortDescription: API to manage objects + documentation: 'https://objects-and-objecttypes-api.readthedocs.io/' + apiDocumentation: 'https://raw.githubusercontent.com/maykinmedia/objects-api/master/src/objects/api/v1/openapi.yaml' + features: + - Objects API + - Minimalistic object management interface + genericName: API component + longDescription: > + The **Objects API** aims to easily store various objects and make them available in + standardized format. The Objects API can be used by any organization to manage + relevant objects. An organization can also choose to use the Objects API to + expose objects to the public, as Open Data. + + To define the format of objects, so called object types, organizations can use + a national and/or local `Objecttypes API`_. + +legal: + license: EUPL-1.2 + mainCopyrightOwner: Maykin Media + repoOwner: Maykin Media + +dependsOn: + open: + - name: Objecttypes API + optional: false + versionMin: '1.0' + - name: PostgreSQL + optional: false + versionMin: '14.0' + - name: PostGIS + optional: false + versionMin: '3.2' + - name: Kubernetes + optional: true + versionMin: '1.12' + - name: Docker + optional: true + versionMin: '18.0' + +inputTypes: + - application/json + +outputTypes: + - application/json + - text/html + +intendedAudience: + countries: + - nl + scope: + - government + +localisation: + availableLanguages: + - nl + - en + localisationReady: false + +maintenance: + type: contract + contractors: + - name: Maykin Media + email: info@maykinmedia.nl + website: https://www.maykinmedia.nl/ + contacts: + - name: Joeri Bekker + affiliation: Maykin Media \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode 2.yml b/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode 2.yml new file mode 100644 index 0000000..b8ec6b7 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode 2.yml @@ -0,0 +1,131 @@ +publiccodeYmlVersion: "0.4" + +name: Medusa +applicationSuite: MegaProductivitySuite +url: "https://example.com/italia/medusa.git" +landingURL: "https://example.com/italia/medusa" +isBasedOn: "https://github.com/italia/otello.git" +softwareVersion: "1.0" +releaseDate: "2017-04-15" +logo: img/logo.svg + +platforms: + - android + - ios + +categories: + - content-management + - office + +usedBy: + - Comune di Firenze + - Comune di Roma + +roadmap: "https://example.com/italia/medusa/roadmap" + +developmentStatus: development + +softwareType: "standalone/desktop" + +intendedAudience: + scope: + - science-and-technology + countries: + - it + - de + unsupportedCountries: + - us + +description: + en: + localisedName: Medusa + shortDescription: > + This description can have a maximum 150 + characters long. We should not fill the + remaining space with "Lorem Ipsum". End + + longDescription: > + Very long description of this software, also split + on multiple rows. You should note what the software + is and why one should need it. + It can also contain some basic Markdown. + + documentation: "https://read.the.documentation/medusa/v1.0" + apiDocumentation: "https://read.the.api.doc/medusa/v1.0" + + features: + - Very important feature + - Will run without a problem + - Has zero bugs + - Solves all the problems of the world + screenshots: + - img/sshot1.jpg + - img/sshot2.jpg + - img/sshot3.jpg + videos: + - https://youtube.com/xxxxxxxx + awards: + - 1st Price Software of the year + +legal: + license: AGPL-3.0-or-later + mainCopyrightOwner: City of Chicago + repoOwner: City of Chicago + +maintenance: + type: "contract" + + contractors: + - name: "Fornitore Privato SPA" + email: "dario.bianchi@fornitore.it" + website: "https://privatecompany.com" + until: "2019-01-01" + + contacts: + - name: Francesco Rossi + email: "francesco.rossi@comune.reggioemilia.it" + affiliation: Comune di Reggio Emilia + phone: "+3923113215112" + +localisation: + localisationReady: true + availableLanguages: + - en + - it + - fr + - de + +dependsOn: + open: + - name: MySQL + versionMin: "1.1" + versionMax: "1.3" + optional: true + - name: PostgreSQL + version: "3.2" + optional: true + proprietary: + - name: Oracle + versionMin: "11.4" + - name: IBM SoftLayer + hardware: + - name: NFC Reader + optional: true + +it: + countryExtensionVersion: "1.0" + + conforme: + lineeGuidaDesign: true + modelloInteroperabilita: true + misureMinimeSicurezza: true + gdpr: true + + piattaforme: + spid: true + cie: true + anpr: true + pagopa: true + + riuso: + codiceIPA: c_h501 \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode.yml b/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode.yml new file mode 100644 index 0000000..b8ec6b7 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/publicCode-Example/publiccode.yml @@ -0,0 +1,131 @@ +publiccodeYmlVersion: "0.4" + +name: Medusa +applicationSuite: MegaProductivitySuite +url: "https://example.com/italia/medusa.git" +landingURL: "https://example.com/italia/medusa" +isBasedOn: "https://github.com/italia/otello.git" +softwareVersion: "1.0" +releaseDate: "2017-04-15" +logo: img/logo.svg + +platforms: + - android + - ios + +categories: + - content-management + - office + +usedBy: + - Comune di Firenze + - Comune di Roma + +roadmap: "https://example.com/italia/medusa/roadmap" + +developmentStatus: development + +softwareType: "standalone/desktop" + +intendedAudience: + scope: + - science-and-technology + countries: + - it + - de + unsupportedCountries: + - us + +description: + en: + localisedName: Medusa + shortDescription: > + This description can have a maximum 150 + characters long. We should not fill the + remaining space with "Lorem Ipsum". End + + longDescription: > + Very long description of this software, also split + on multiple rows. You should note what the software + is and why one should need it. + It can also contain some basic Markdown. + + documentation: "https://read.the.documentation/medusa/v1.0" + apiDocumentation: "https://read.the.api.doc/medusa/v1.0" + + features: + - Very important feature + - Will run without a problem + - Has zero bugs + - Solves all the problems of the world + screenshots: + - img/sshot1.jpg + - img/sshot2.jpg + - img/sshot3.jpg + videos: + - https://youtube.com/xxxxxxxx + awards: + - 1st Price Software of the year + +legal: + license: AGPL-3.0-or-later + mainCopyrightOwner: City of Chicago + repoOwner: City of Chicago + +maintenance: + type: "contract" + + contractors: + - name: "Fornitore Privato SPA" + email: "dario.bianchi@fornitore.it" + website: "https://privatecompany.com" + until: "2019-01-01" + + contacts: + - name: Francesco Rossi + email: "francesco.rossi@comune.reggioemilia.it" + affiliation: Comune di Reggio Emilia + phone: "+3923113215112" + +localisation: + localisationReady: true + availableLanguages: + - en + - it + - fr + - de + +dependsOn: + open: + - name: MySQL + versionMin: "1.1" + versionMax: "1.3" + optional: true + - name: PostgreSQL + version: "3.2" + optional: true + proprietary: + - name: Oracle + versionMin: "11.4" + - name: IBM SoftLayer + hardware: + - name: NFC Reader + optional: true + +it: + countryExtensionVersion: "1.0" + + conforme: + lineeGuidaDesign: true + modelloInteroperabilita: true + misureMinimeSicurezza: true + gdpr: true + + piattaforme: + spid: true + cie: true + anpr: true + pagopa: true + + riuso: + codiceIPA: c_h501 \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/r3broot2/codemeta.json b/src/somef_core/test/test_data/repositories/r3broot2/codemeta.json new file mode 100644 index 0000000..742d865 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/r3broot2/codemeta.json @@ -0,0 +1,437 @@ +{ + "@context": "https://doi.org/10.5063/schema/codemeta-2.0", + "@type": "SoftwareSourceCode", + "license": "https://spdx.org/licenses/GPL-3.0", + "codeRepository": "https://github.com/R3BRootGroup/R3BRoot", + "contIntegration": "https://github.com/R3BRootGroup/R3BRoot/actions", + "name": "R3BRoot", + "softwareVersion": "24.0.0", + "description": "Software for simulations and data analysis of Reactions with Relativistic Radioactive Beams (R3B) experiments at GSI/FAIR", + "dateCreated": "2009-04-14", + "datePublished": "2009-08-01", + "dateModified": "2024-12-06", + "downloadUrl": "https://github.com/R3BRootGroup/R3BRoot/archive/refs/tags/dec24.tar.gz", + "issueTracker": "https://github.com/R3BRootGroup/R3BRoot/issues", + "readme": "https://github.com/R3BRootGroup/R3BRoot/blob/dev/README.md", + "relatedLink": "https://www.gsi.de/work/forschung/nustarenna/nustarenna_divisions/kernreaktionen/activities/r3b", + "releaseNotes": "", + "identifier": "https://doi.org/10.5281/zenodo.5549469", + "memoryRequirements": "8 GB of RAM (minimum), 16 GB recommended for large simulations or data analysis", + "processorRequirements": "Intel Core i5 or equivalent (minimum), i7 or better recommended for optimal performance", + "storageRequirements": "At least 2 GB of free disk space for the software", + "copyrightHolder": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany", + "funder": "", + "funding": "", + "applicationCategory": "Nuclear physics", + "developmentStatus": "active", + "referencePublication": "https://doi.org/10.1088/1742-6596/523/1/012034", + "keywords": [ + "Geant4", + "c-plus-plus", + "cmake", + "vmc", + "modular", + "Track reconstruction", + "Simulation", + "Data analysis", + "Structure and dynamics of nuclei", + "Nuclear reactions", + "Nuclear fission", + "Hypernuclei", + "Equation of state", + "Short range NN correlations", + "R3B experiments", + "GSI/FAIR facility" + ], + "programmingLanguage": [ + "C", + "C++" + ], + "runtimePlatform": [ + "ROOT" + ], + "operatingSystem": [ + "Linux", + "macOS" + ], + "softwareRequirements": [ + "FairRoot, FairSoft" + ], + "maintainer": { + "@type": "Person", + "givenName": "Jose Luis", + "familyName": "Rodriguez Sanchez", + "@id": "https://orcid.org/0000-0002-4702-5294", + "affiliation": "CITENI, Industrial Campus of Ferrol, University of Coru\u00f1a, 15403 Ferrol, Spain" + }, + "author": [ + { + "@type": "Person", + "givenName": "Jose Luis", + "familyName": "Rodr\u00edguez-S\u00e1nchez", + "email": "j.l.rodriguez.sanchez@udc.es", + "affiliation": "CITENI, Industrial Campus of Ferrol, University of Coru\u00f1a, 15403 Ferrol, Spain", + "identifier": "https://orcid.org/0000-0002-4702-5294" + }, + { + "@type": "Person", + "givenName": "Hector", + "familyName": "Alvarez Pol", + "email": "hector.alvarez@usc.es", + "affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain", + "identifier": "https://orcid.org/0000-0001-9643-6252" + }, + { + "@type": "Person", + "givenName": "Leyla", + "familyName": "Atar", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Antoine", + "familyName": "Barriere", + "affiliation": "GANIL, 14000 Caen, France" + }, + { + "@type": "Person", + "givenName": "Lukas", + "familyName": "Bott", + "affiliation": "Goethe University Frankfurt, 60629 Frankfurt am Main, Germany" + }, + { + "@type": "Person", + "givenName": "Audrey", + "familyName": "Chatillon" + }, + { + "@type": "Person", + "givenName": "Martina", + "familyName": "Feijoo-Font\u00e1n", + "affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain" + }, + { + "@type": "Person", + "givenName": "Gabriel", + "familyName": "Garc\u00eda-Jim\u00e9nez", + "affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain" + }, + { + "@type": "Person", + "givenName": "Igor", + "familyName": "Gasparic", + "affiliation": "RBI Zagreb, HR10000 Zagreb, Croatia" + }, + { + "@type": "Person", + "givenName": "Antia", + "familyName": "Gra\u00f1a-Gonz\u00e1lez", + "affiliation": "CITENI, Industrial Campus of Ferrol, University of Coru\u00f1a, 15403 Ferrol, Spain" + }, + { + "@type": "Person", + "givenName": "Michael", + "familyName": "Heil", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Andrea", + "familyName": "Horvat", + "affiliation": "RBI Zagreb, HR10000 Zagreb, Croatia" + }, + { + "@type": "Person", + "givenName": "Andrea", + "familyName": "Jedele", + "affiliation": "Technische Universit\u00e4t Darmstadt, Fachbereich Physik, Institut f\u00fcr Kernphysik, 64289 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "H\u00e5kan", + "familyName": "Johansson", + "affiliation": "Institutionen f\u00f6r Fysik, Chalmers Tekniska H\u00f6gskola, 412 96 G\u00f6teborg, Sweden" + }, + { + "@type": "Person", + "givenName": "Aleksandra", + "familyName": "Kelic-Heil", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Philipp", + "familyName": "Klenze", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Dmytro", + "familyName": "Kresan", + "email": "d.kresan@gsi.de", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany", + "identifier": "https://orcid.org/0000-0002-7537-2875" + }, + { + "@type": "Person", + "givenName": "Eleonora", + "familyName": "Kudaibergenova" + }, + { + "@type": "Person", + "givenName": "Andrea", + "familyName": "Lagni", + "affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain" + }, + { + "@type": "Person", + "givenName": "Ivana", + "familyName": "Lihtar", + "affiliation": "RBI Zagreb, HR10000 Zagreb, Croatia" + }, + { + "@type": "Person", + "givenName": "Leandro", + "familyName": "Milhomens da Fonseca", + "affiliation": "Technische Universit\u00e4t Darmstadt, Fachbereich Physik, Institut f\u00fcr Kernphysik, 64289 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Pierre", + "familyName": "Morfouace", + "affiliation": "CEA, DAM, DIF, 91297 Arpajon, France" + }, + { + "@type": "Person", + "givenName": "Bastian", + "familyName": "Loeher" + }, + { + "@type": "Person", + "givenName": "Jan", + "familyName": "Mayer" + }, + { + "@type": "Person", + "givenName": "Nikhil", + "familyName": "Mozumdar" + }, + { + "@type": "Person", + "givenName": "Valerii", + "familyName": "Panin", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Ryo", + "familyName": "Taniuchi", + "affiliation": "School of Physics, Engineering and Technology, University of York, YO10 5DD York, United Kingdom" + }, + { + "@type": "Person", + "givenName": "Hans", + "familyName": "T\u00f6rnqvist", + "affiliation": "Institutionen f\u00f6r Fysik, Chalmers Tekniska H\u00f6gskola, 412 96 G\u00f6teborg, Sweden" + }, + { + "@type": "Person", + "givenName": "Vadim", + "familyName": "Wagner" + }, + { + "@type": "Person", + "givenName": "Yanzhao", + "familyName": "Wang", + "affiliation": "Universit\u00e4t zu K\u00f6ln, 50923 K\u00f6ln, Germany" + }, + { + "@type": "Person", + "givenName": "Matthew", + "familyName": "Whitehead" + }, + { + "@type": "Person", + "givenName": "Manuel", + "familyName": "Xarepe", + "affiliation": "Faculty of Science of the University of Lisbon, 1749-016 Lisboa, Portugal" + }, + { + "@type": "Person", + "givenName": "Laurent", + "familyName": "Audouin", + "email": "laurent.audouin@ijclab.in2p3.fr", + "affiliation": "IPN Orsay, 91406 Orsay, France", + "identifier": "https://orcid.org/0000-0001-9899-6923" + } + ], + "contributor": [ + { + "@type": "Person", + "givenName": "Mohammad", + "familyName": "Al-Turany", + "affiliation": "GSI Helmholtzzentrum f\u00fcr Schwerionenforschung, 64291 Darmstadt, Germany" + }, + { + "@type": "Person", + "givenName": "Laurent", + "familyName": "Audouin", + "affiliation": "IPN Orsay, 91406 Orsay, France" + }, + { + "@type": "Person", + "givenName": "Martin", + "familyName": "Bajzek" + }, + { + "@type": "Person", + "givenName": "Konstanze", + "familyName": "Boretzky" + }, + { + "@type": "Person", + "givenName": "Pablo", + "familyName": "Cabanelas", + "affiliation": "IGFAE, University of Santiago de Compostela, 15782 Santiago de Compostela, Spain" + }, + { + "@type": "Person", + "givenName": "Christiaan", + "familyName": "Douma" + }, + { + "@type": "Person", + "givenName": "Ashton", + "familyName": "Falduto" + }, + { + "@type": "Person", + "givenName": "Daniel", + "familyName": "Galaviz", + "affiliation": "Faculty of Science of the University of Lisbon, 1749-016 Lisboa, Portugal" + }, + { + "@type": "Person", + "givenName": "Elisabet", + "familyName": "Galiana" + }, + { + "@type": "Person", + "givenName": "Roman", + "familyName": "Gernh\u00e4user", + "affiliation": "Technische Universit\u00e4t M\u00fcnchen, 85748 Garching, Germany" + }, + { + "@type": "Person", + "givenName": "Benjamin", + "familyName": "Heiss" + }, + { + "@type": "Person", + "givenName": "Alexander", + "familyName": "Inglessi" + }, + { + "@type": "Person", + "givenName": "De\u0161a", + "familyName": "Jelavic-Malenica" + }, + { + "@type": "Person", + "givenName": "Tobias", + "familyName": "Jenegger" + }, + { + "@type": "Person", + "givenName": "Aron", + "familyName": "Kripko" + }, + { + "@type": "Person", + "givenName": "Marc", + "familyName": "Labiche", + "affiliation": "STFC Daresbury Laboratory, Warrington, United Kingdom" + }, + { + "@type": "Person", + "givenName": "Enis", + "familyName": "Lorenz" + }, + { + "@type": "Person", + "givenName": "Stefanos", + "familyName": "Paschalis", + "affiliation": "School of Physics, Engineering and Technology, University of York, YO10 5DD York, United Kingdom" + }, + { + "@type": "Person", + "givenName": "Angel", + "familyName": "Perea" + }, + { + "@type": "Person", + "givenName": "Ralf", + "familyName": "Plag" + }, + { + "@type": "Person", + "givenName": "Lukas", + "familyName": "Ponnath" + }, + { + "@type": "Person", + "givenName": "Christine", + "familyName": "Qi" + }, + { + "@type": "Person", + "givenName": "Alexey", + "familyName": "Rybalchenko" + }, + { + "@type": "Person", + "givenName": "Luke", + "familyName": "Rose" + }, + { + "@type": "Person", + "givenName": "Dominic", + "familyName": "Rossi" + }, + { + "@type": "Person", + "givenName": "Deniz", + "familyName": "Savran" + }, + { + "@type": "Person", + "givenName": "Sonja", + "familyName": "Storck" + }, + { + "@type": "Person", + "givenName": "Christian", + "familyName": "S\u00fcrder" + }, + { + "@type": "Person", + "givenName": "Ina", + "familyName": "Syndikus" + }, + { + "@type": "Person", + "givenName": "Joachim", + "familyName": "Tscheuschner" + }, + { + "@type": "Person", + "givenName": "Alicia", + "familyName": "Wongel" + }, + { + "@type": "Person", + "givenName": "Lorenzo", + "familyName": "Zanetti" + } + ] + } \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/repos_oeg/test-category.json b/src/somef_core/test/test_data/repositories/repos_oeg/test-category.json new file mode 100644 index 0000000..7a49a8e --- /dev/null +++ b/src/somef_core/test/test_data/repositories/repos_oeg/test-category.json @@ -0,0 +1,238 @@ +{ + "code_repository": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/oeg-upm/devops-infra" + }, + "technique": "GitHub_API" + } + ], + "date_created": [ + { + "confidence": 1, + "result": { + "type": "Date", + "value": "2020-12-30T19:56:43Z" + }, + "technique": "GitHub_API" + } + ], + "date_updated": [ + { + "confidence": 1, + "result": { + "type": "Date", + "value": "2025-11-11T18:43:08Z" + }, + "technique": "GitHub_API" + } + ], + "description": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "Public repository for an ontology network on DevOps infrastructure" + }, + "technique": "GitHub_API" + } + ], + "download_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/oeg-upm/devops-infra/releases" + }, + "technique": "GitHub_API" + } + ], + "forks_count": [ + { + "confidence": 1, + "result": { + "type": "Number", + "value": 2 + }, + "technique": "GitHub_API" + } + ], + "forks_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://api.github.com/repos/oeg-upm/devops-infra/forks" + }, + "technique": "GitHub_API" + } + ], + "full_name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "oeg-upm/devops-infra" + }, + "technique": "GitHub_API" + } + ], + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "DevOps Infrastructure Ontology Network" + }, + "source": "https://raw.githubusercontent.com/oeg-upm/devops-infra/master/README.md", + "technique": "regular_expression" + } + ], + "homepage": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "http://w3id.org/devops-infra" + }, + "technique": "GitHub_API" + } + ], + "identifier": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://zenodo.org/badge/latestdoi/325636796" + }, + "source": "https://raw.githubusercontent.com/oeg-upm/devops-infra/master/README.md", + "technique": "regular_expression" + } + ], + "issue_tracker": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://api.github.com/repos/oeg-upm/devops-infra/issues" + }, + "technique": "GitHub_API" + } + ], + "name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "devops-infra" + }, + "technique": "GitHub_API" + } + ], + "owner": [ + { + "confidence": 1, + "result": { + "type": "Organization", + "value": "oeg-upm" + }, + "technique": "GitHub_API" + } + ], + "programming_languages": [ + { + "confidence": 1, + "result": { + "name": "HTML", + "size": 707430, + "type": "Programming_language", + "value": "HTML" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "name": "CSS", + "size": 127691, + "type": "Programming_language", + "value": "CSS" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "name": "JavaScript", + "size": 9024, + "type": "Programming_language", + "value": "JavaScript" + }, + "technique": "GitHub_API" + } + ], + "readme_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/oeg-upm/devops-infra/master/README.md" + }, + "technique": "file_exploration" + } + ], + "releases": [ + { + "confidence": 1, + "result": { + "assets": [], + "author": { + "name": "ocorcho", + "type": "User" + }, + "date_created": "2021-04-19T15:27:52Z", + "date_published": "2021-04-19T15:33:02Z", + "description": "First official release of this Ontology Network for the representation of a DevOps infrastructure. It consists of 10 interrelated ontologies, which represent different aspects of such an infrastructure.\r\n\r\nThis release also includes a set of 16 SKOS concept schemes, with their corresponding SKOS concepts, and several HTML files for the publication of the catalogue of ontologies and thesauri.", + "html_url": "https://github.com/oeg-upm/devops-infra/releases/tag/1.0.0", + "name": "First official version", + "release_id": 41653525, + "tag": "1.0.0", + "tarball_url": "https://api.github.com/repos/oeg-upm/devops-infra/tarball/1.0.0", + "type": "Release", + "url": "https://api.github.com/repos/oeg-upm/devops-infra/releases/41653525", + "value": "https://api.github.com/repos/oeg-upm/devops-infra/releases/41653525", + "zipball_url": "https://api.github.com/repos/oeg-upm/devops-infra/zipball/1.0.0" + }, + "technique": "GitHub_API" + } + ], + "requirements": [ + { + "confidence": 1, + "result": { + "original_header": "Ontology network requirements", + "type": "Text_excerpt", + "value": "The list of requirements of the ontology network is available [here](https://github.com/oeg-upm/devops-infra/blob/master/Requirements.xlsx). New requirements or issues can be submitted in [here](https://github.com/oeg-upm/devops-infra/issues)\n" + }, + "source": "https://raw.githubusercontent.com/oeg-upm/devops-infra/master/README.md", + "technique": "header_analysis" + } + ], + "somef_provenance": { + "date": "2026-01-20 09:20:36", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "stargazers_count": [ + { + "confidence": 1, + "result": { + "type": "Number", + "value": 13 + }, + "technique": "GitHub_API" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/rustdesk/Cargo 2.toml b/src/somef_core/test/test_data/repositories/rustdesk/Cargo 2.toml new file mode 100644 index 0000000..6cf0e5b --- /dev/null +++ b/src/somef_core/test/test_data/repositories/rustdesk/Cargo 2.toml @@ -0,0 +1,223 @@ +[package] +name = "rustdesk" +version = "1.4.0" +authors = ["rustdesk "] +edition = "2021" +build= "build.rs" +description = "RustDesk Remote Desktop" +default-run = "rustdesk" +rust-version = "1.75" + +[lib] +name = "librustdesk" +crate-type = ["cdylib", "staticlib", "rlib"] + +[[bin]] +name = "naming" +path = "src/naming.rs" + +[[bin]] +name = "service" +path = "src/service.rs" + +[features] +inline = [] +cli = [] +use_samplerate = ["samplerate"] +use_rubato = ["rubato"] +use_dasp = ["dasp"] +flutter = ["flutter_rust_bridge"] +default = ["use_dasp"] +hwcodec = ["scrap/hwcodec"] +vram = ["scrap/vram"] +mediacodec = ["scrap/mediacodec"] +plugin_framework = [] +linux-pkg-config = ["magnum-opus/linux-pkg-config", "scrap/linux-pkg-config"] +unix-file-copy-paste = [ + "dep:x11-clipboard", + "dep:x11rb", + "dep:percent-encoding", + "dep:once_cell", + "clipboard/unix-file-copy-paste", +] +screencapturekit = ["cpal/screencapturekit"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1" +scrap = { path = "libs/scrap", features = ["wayland"] } +hbb_common = { path = "libs/hbb_common" } +serde_derive = "1.0" +serde = "1.0" +serde_json = "1.0" +serde_repr = "0.1" +cfg-if = "1.0" +lazy_static = "1.4" +sha2 = "0.10" +repng = "0.2" +parity-tokio-ipc = { git = "https://github.com/rustdesk-org/parity-tokio-ipc" } +magnum-opus = { git = "https://github.com/rustdesk-org/magnum-opus" } +dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } +rubato = { version = "0.12", optional = true } +samplerate = { version = "0.2", optional = true } +uuid = { version = "1.3", features = ["v4"] } +clap = "4.2" +rpassword = "7.2" +num_cpus = "1.15" +bytes = { version = "1.4", features = ["serde"] } +default-net = "0.14" +wol-rs = "1.0" +flutter_rust_bridge = { version = "=1.80", features = ["uuid"], optional = true} +errno = "0.3" +rdev = { git = "https://github.com/rustdesk-org/rdev" } +url = { version = "2.3", features = ["serde"] } +crossbeam-queue = "0.3" +hex = "0.4" +chrono = "0.4" +cidr-utils = "0.5" +libloading = "0.8" +fon = "0.6" +zip = "0.6" +shutdown_hooks = "0.1" +totp-rs = { version = "5.4", default-features = false, features = ["gen_secret", "otpauth"] } + +[target.'cfg(not(target_os = "linux"))'.dependencies] +# https://github.com/rustdesk/rustdesk/discussions/10197, not use cpal on linux +cpal = { git = "https://github.com/rustdesk-org/cpal", branch = "osx-screencapturekit" } +ringbuf = "0.3" + +[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] +mac_address = "1.1" +sciter-rs = { git = "https://github.com/rustdesk-org/rust-sciter", branch = "dyn" } +sys-locale = "0.3" +enigo = { path = "libs/enigo", features = [ "with_serde" ] } +clipboard = { path = "libs/clipboard" } +ctrlc = "3.2" +# arboard = { version = "3.4", features = ["wayland-data-control"] } +arboard = { git = "https://github.com/rustdesk-org/arboard", features = ["wayland-data-control"] } +clipboard-master = { git = "https://github.com/rustdesk-org/clipboard-master" } + +system_shutdown = "4.0" +qrcode-generator = "4.1" + +[target.'cfg(target_os = "windows")'.dependencies] +winapi = { version = "0.3", features = [ + "winuser", + "wincrypt", + "shellscalingapi", + "pdh", + "synchapi", + "memoryapi", + "shellapi", + "devguid", + "setupapi", + "cguid", + "cfgmgr32", + "ioapiset", + "winspool", +] } +windows = { version = "0.61", features = [ + "Win32", + "Win32_System", + "Win32_System_Diagnostics", + "Win32_System_Threading", + "Win32_System_Diagnostics_ToolHelp", +] } +winreg = "0.11" +windows-service = "0.6" +virtual_display = { path = "libs/virtual_display" } +remote_printer = { path = "libs/remote_printer" } +impersonate_system = { git = "https://github.com/rustdesk-org/impersonate-system" } +shared_memory = "0.12" +tauri-winrt-notification = "0.1" +runas = "1.2" + +[target.'cfg(target_os = "macos")'.dependencies] +objc = "0.2" +cocoa = "0.24" +dispatch = "0.2" +core-foundation = "0.9" +core-graphics = "0.22" +include_dir = "0.7" +fruitbasket = "0.10" +objc_id = "0.1" + +[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies] +tray-icon = { git = "https://github.com/tauri-apps/tray-icon" } +tao = { git = "https://github.com/rustdesk-org/tao", branch = "dev" } +image = "0.24" + +[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies] +keepawake = { git = "https://github.com/rustdesk-org/keepawake-rs" } + +[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies] +wallpaper = { git = "https://github.com/rustdesk-org/wallpaper.rs" } + +[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies] +# https://github.com/rustdesk/rustdesk-server-pro/issues/189, using native-tls for better tls support +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "native-tls", "gzip"], default-features=false } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows")))'.dependencies] +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false } + +[target.'cfg(target_os = "linux")'.dependencies] +psimple = { package = "libpulse-simple-binding", version = "2.27" } +pulse = { package = "libpulse-binding", version = "2.27" } +rust-pulsectl = { git = "https://github.com/rustdesk-org/pulsectl" } +async-process = "1.7" +evdev = { git="https://github.com/rustdesk-org/evdev" } +dbus = "0.9" +dbus-crossroads = "0.5" +pam = { git="https://github.com/rustdesk-org/pam" } +users = { version = "0.11" } +x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true} +x11rb = {version = "0.12", features = ["all-extensions"], optional = true} +percent-encoding = {version = "2.3", optional = true} +once_cell = {version = "1.18", optional = true} +nix = { version = "0.29", features = ["term", "process"]} +gtk = "0.18" +termios = "0.3" + +[target.'cfg(target_os = "android")'.dependencies] +android_logger = "0.13" +jni = "0.21" +android-wakelock = { git = "https://github.com/rustdesk-org/android-wakelock" } + +[workspace] +members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable", "libs/remote_printer"] +exclude = ["vdi/host", "examples/custom_plugin"] + +[package.metadata.winres] +LegalCopyright = "Copyright © 2025 Purslane Ltd. All rights reserved." +ProductName = "RustDesk" +FileDescription = "RustDesk Remote Desktop" +OriginalFilename = "rustdesk.exe" + +[target.'cfg(target_os="windows")'.build-dependencies] +winres = "0.1" +winapi = { version = "0.3", features = [ "winnt", "pdh", "synchapi" ] } + +[build-dependencies] +cc = "1.0" +hbb_common = { path = "libs/hbb_common" } +os-version = "0.2" + +[dev-dependencies] +hound = "3.5" +docopt = "1.1" + +[package.metadata.bundle] +name = "RustDesk" +identifier = "com.carriez.rustdesk" +icon = ["res/32x32.png", "res/128x128.png", "res/128x128@2x.png"] +osx_minimum_system_version = "10.14" + +#https://github.com/johnthagen/min-sized-rust +[profile.release] +lto = true +codegen-units = 1 +panic = 'abort' +strip = true +#opt-level = 'z' # only have smaller size after strip +rpath = true diff --git a/src/somef_core/test/test_data/repositories/rustdesk/Cargo.toml b/src/somef_core/test/test_data/repositories/rustdesk/Cargo.toml new file mode 100644 index 0000000..6cf0e5b --- /dev/null +++ b/src/somef_core/test/test_data/repositories/rustdesk/Cargo.toml @@ -0,0 +1,223 @@ +[package] +name = "rustdesk" +version = "1.4.0" +authors = ["rustdesk "] +edition = "2021" +build= "build.rs" +description = "RustDesk Remote Desktop" +default-run = "rustdesk" +rust-version = "1.75" + +[lib] +name = "librustdesk" +crate-type = ["cdylib", "staticlib", "rlib"] + +[[bin]] +name = "naming" +path = "src/naming.rs" + +[[bin]] +name = "service" +path = "src/service.rs" + +[features] +inline = [] +cli = [] +use_samplerate = ["samplerate"] +use_rubato = ["rubato"] +use_dasp = ["dasp"] +flutter = ["flutter_rust_bridge"] +default = ["use_dasp"] +hwcodec = ["scrap/hwcodec"] +vram = ["scrap/vram"] +mediacodec = ["scrap/mediacodec"] +plugin_framework = [] +linux-pkg-config = ["magnum-opus/linux-pkg-config", "scrap/linux-pkg-config"] +unix-file-copy-paste = [ + "dep:x11-clipboard", + "dep:x11rb", + "dep:percent-encoding", + "dep:once_cell", + "clipboard/unix-file-copy-paste", +] +screencapturekit = ["cpal/screencapturekit"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +async-trait = "0.1" +scrap = { path = "libs/scrap", features = ["wayland"] } +hbb_common = { path = "libs/hbb_common" } +serde_derive = "1.0" +serde = "1.0" +serde_json = "1.0" +serde_repr = "0.1" +cfg-if = "1.0" +lazy_static = "1.4" +sha2 = "0.10" +repng = "0.2" +parity-tokio-ipc = { git = "https://github.com/rustdesk-org/parity-tokio-ipc" } +magnum-opus = { git = "https://github.com/rustdesk-org/magnum-opus" } +dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } +rubato = { version = "0.12", optional = true } +samplerate = { version = "0.2", optional = true } +uuid = { version = "1.3", features = ["v4"] } +clap = "4.2" +rpassword = "7.2" +num_cpus = "1.15" +bytes = { version = "1.4", features = ["serde"] } +default-net = "0.14" +wol-rs = "1.0" +flutter_rust_bridge = { version = "=1.80", features = ["uuid"], optional = true} +errno = "0.3" +rdev = { git = "https://github.com/rustdesk-org/rdev" } +url = { version = "2.3", features = ["serde"] } +crossbeam-queue = "0.3" +hex = "0.4" +chrono = "0.4" +cidr-utils = "0.5" +libloading = "0.8" +fon = "0.6" +zip = "0.6" +shutdown_hooks = "0.1" +totp-rs = { version = "5.4", default-features = false, features = ["gen_secret", "otpauth"] } + +[target.'cfg(not(target_os = "linux"))'.dependencies] +# https://github.com/rustdesk/rustdesk/discussions/10197, not use cpal on linux +cpal = { git = "https://github.com/rustdesk-org/cpal", branch = "osx-screencapturekit" } +ringbuf = "0.3" + +[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] +mac_address = "1.1" +sciter-rs = { git = "https://github.com/rustdesk-org/rust-sciter", branch = "dyn" } +sys-locale = "0.3" +enigo = { path = "libs/enigo", features = [ "with_serde" ] } +clipboard = { path = "libs/clipboard" } +ctrlc = "3.2" +# arboard = { version = "3.4", features = ["wayland-data-control"] } +arboard = { git = "https://github.com/rustdesk-org/arboard", features = ["wayland-data-control"] } +clipboard-master = { git = "https://github.com/rustdesk-org/clipboard-master" } + +system_shutdown = "4.0" +qrcode-generator = "4.1" + +[target.'cfg(target_os = "windows")'.dependencies] +winapi = { version = "0.3", features = [ + "winuser", + "wincrypt", + "shellscalingapi", + "pdh", + "synchapi", + "memoryapi", + "shellapi", + "devguid", + "setupapi", + "cguid", + "cfgmgr32", + "ioapiset", + "winspool", +] } +windows = { version = "0.61", features = [ + "Win32", + "Win32_System", + "Win32_System_Diagnostics", + "Win32_System_Threading", + "Win32_System_Diagnostics_ToolHelp", +] } +winreg = "0.11" +windows-service = "0.6" +virtual_display = { path = "libs/virtual_display" } +remote_printer = { path = "libs/remote_printer" } +impersonate_system = { git = "https://github.com/rustdesk-org/impersonate-system" } +shared_memory = "0.12" +tauri-winrt-notification = "0.1" +runas = "1.2" + +[target.'cfg(target_os = "macos")'.dependencies] +objc = "0.2" +cocoa = "0.24" +dispatch = "0.2" +core-foundation = "0.9" +core-graphics = "0.22" +include_dir = "0.7" +fruitbasket = "0.10" +objc_id = "0.1" + +[target.'cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))'.dependencies] +tray-icon = { git = "https://github.com/tauri-apps/tray-icon" } +tao = { git = "https://github.com/rustdesk-org/tao", branch = "dev" } +image = "0.24" + +[target.'cfg(any(target_os = "macos", target_os = "linux"))'.dependencies] +keepawake = { git = "https://github.com/rustdesk-org/keepawake-rs" } + +[target.'cfg(any(target_os = "windows", target_os = "linux"))'.dependencies] +wallpaper = { git = "https://github.com/rustdesk-org/wallpaper.rs" } + +[target.'cfg(any(target_os = "macos", target_os = "windows"))'.dependencies] +# https://github.com/rustdesk/rustdesk-server-pro/issues/189, using native-tls for better tls support +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "native-tls", "gzip"], default-features=false } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows")))'.dependencies] +reqwest = { git = "https://github.com/rustdesk-org/reqwest", features = ["blocking", "socks", "json", "rustls-tls", "rustls-tls-native-roots", "gzip"], default-features=false } + +[target.'cfg(target_os = "linux")'.dependencies] +psimple = { package = "libpulse-simple-binding", version = "2.27" } +pulse = { package = "libpulse-binding", version = "2.27" } +rust-pulsectl = { git = "https://github.com/rustdesk-org/pulsectl" } +async-process = "1.7" +evdev = { git="https://github.com/rustdesk-org/evdev" } +dbus = "0.9" +dbus-crossroads = "0.5" +pam = { git="https://github.com/rustdesk-org/pam" } +users = { version = "0.11" } +x11-clipboard = {git="https://github.com/clslaid/x11-clipboard", branch = "feat/store-batch", optional = true} +x11rb = {version = "0.12", features = ["all-extensions"], optional = true} +percent-encoding = {version = "2.3", optional = true} +once_cell = {version = "1.18", optional = true} +nix = { version = "0.29", features = ["term", "process"]} +gtk = "0.18" +termios = "0.3" + +[target.'cfg(target_os = "android")'.dependencies] +android_logger = "0.13" +jni = "0.21" +android-wakelock = { git = "https://github.com/rustdesk-org/android-wakelock" } + +[workspace] +members = ["libs/scrap", "libs/hbb_common", "libs/enigo", "libs/clipboard", "libs/virtual_display", "libs/virtual_display/dylib", "libs/portable", "libs/remote_printer"] +exclude = ["vdi/host", "examples/custom_plugin"] + +[package.metadata.winres] +LegalCopyright = "Copyright © 2025 Purslane Ltd. All rights reserved." +ProductName = "RustDesk" +FileDescription = "RustDesk Remote Desktop" +OriginalFilename = "rustdesk.exe" + +[target.'cfg(target_os="windows")'.build-dependencies] +winres = "0.1" +winapi = { version = "0.3", features = [ "winnt", "pdh", "synchapi" ] } + +[build-dependencies] +cc = "1.0" +hbb_common = { path = "libs/hbb_common" } +os-version = "0.2" + +[dev-dependencies] +hound = "3.5" +docopt = "1.1" + +[package.metadata.bundle] +name = "RustDesk" +identifier = "com.carriez.rustdesk" +icon = ["res/32x32.png", "res/128x128.png", "res/128x128@2x.png"] +osx_minimum_system_version = "10.14" + +#https://github.com/johnthagen/min-sized-rust +[profile.release] +lto = true +codegen-units = 1 +panic = 'abort' +strip = true +#opt-level = 'z' # only have smaller size after strip +rpath = true diff --git a/src/somef_core/test/test_data/repositories/sunpy/pyproject.toml b/src/somef_core/test/test_data/repositories/sunpy/pyproject.toml index 65cf800..1240eae 100644 --- a/src/somef_core/test/test_data/repositories/sunpy/pyproject.toml +++ b/src/somef_core/test/test_data/repositories/sunpy/pyproject.toml @@ -23,7 +23,8 @@ name = "sunpy" description = "SunPy core package: Python for Solar Physics" requires-python = ">=3.11" readme = { file = "README.rst", content-type = "text/x-rst" } -license = { file = "LICENSE.rst" } +license-files = ["LICENSE.rst", "licenses/*.rst"] +license = "BSD-3-Clause" authors = [ { name = "The SunPy Community", email = "sunpy@googlegroups.com" }, ] diff --git a/src/somef_core/test/test_data/repositories/termlex-main/ontology/termlex.ttl b/src/somef_core/test/test_data/repositories/termlex-main/ontology/termlex.ttl new file mode 100644 index 0000000..e56108c --- /dev/null +++ b/src/somef_core/test/test_data/repositories/termlex-main/ontology/termlex.ttl @@ -0,0 +1,2150 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@prefix termlex: . +@prefix prof: . +@prefix dct: . +@base . + + rdf:type owl:Ontology, prof:Profile ; + owl:imports , + rdfs: , + , + , + , + ; + prof:isProfileOf ; + dct:title "Termlex Ontology"@en ; + dct:contributor "Patricia Martín Chozas", "Víctor Rodríguez Doncel", "Thierry Declerck", "Elena Montiel Ponsoda" ; + dct:license ; + dct:created "2022-01-11" ; + rdfs:label "An Ontolex-lemon extension to represent terminological data"@en . + +################################################################# +# Annotation properties +################################################################# + +### http://purl.org/dc/dcam/domainIncludes + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/dcam/rangeIncludes + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/coverage + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/date + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/format + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/identifier + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/language + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/relation + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/source + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/subject + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/type + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/terms/abstract + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/accessRights + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/accrualMethod + rdf:type owl:AnnotationProperty ; + rdfs:domain . + + +### http://purl.org/dc/terms/accrualPeriodicity + rdf:type owl:AnnotationProperty ; + rdfs:domain . + + +### http://purl.org/dc/terms/accrualPolicy + rdf:type owl:AnnotationProperty ; + rdfs:domain . + + +### http://purl.org/dc/terms/alternative + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/audience + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/terms/available + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/bibliographicCitation + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/conformsTo + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/contributor + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/coverage + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/created + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/creator + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/date + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/dateAccepted + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/dateCopyrighted + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/dateSubmitted + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/description + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/educationLevel + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/extent + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/format + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/hasFormat + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/hasPart + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/hasVersion + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/identifier + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/isFormatOf + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/isPartOf + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/isReferencedBy + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/isReplacedBy + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/isRequiredBy + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/isVersionOf + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/issued + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/language + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/license + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/mediator + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/medium + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/modified + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/publisher + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/references + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/relation + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/replaces + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/requires + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/rights + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/source + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/spatial + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/subject + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/tableOfContents + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/temporal + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf , + . + + +### http://purl.org/dc/terms/title + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://purl.org/dc/terms/type + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/valid + rdf:type owl:AnnotationProperty ; + rdfs:subPropertyOf ; + rdfs:range rdfs:Literal . + + +### http://www.w3.org/1999/02/22-rdf-syntax-ns#value +rdf:value rdf:type owl:AnnotationProperty . + + +################################################################# +# Datatypes +################################################################# + +### http://purl.org/dc/terms/Box + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/ISO3166 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/ISO639-2 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/ISO639-3 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/Period + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/Point + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/RFC1766 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/RFC3066 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/RFC4646 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/RFC5646 + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/URI + rdf:type rdfs:Datatype . + + +### http://purl.org/dc/terms/W3CDTF + rdf:type rdfs:Datatype . + + +### http://www.w3.org/2001/XMLSchema#date +xsd:date rdf:type rdfs:Datatype . + + +################################################################# +# Object Properties +################################################################# + +### http://www.w3.org/2004/02/skos/core#inScheme + rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/lexicog#usageExample + rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/lime#entry + rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/ontolex#lexicalForm + rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/ontolex#sense + rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/termlex#definition +:definition rdf:type owl:ObjectProperty . + + +### http://www.w3.org/ns/lemon/termlex#functionalEvokes +:functionalEvokes rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf ; + owl:inverseOf :functionalIsEvokedBy . + + +### http://www.w3.org/ns/lemon/termlex#functionalIsEvokedBy +:functionalIsEvokedBy rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf ; + rdf:type owl:FunctionalProperty ; + rdfs:domain ; + rdfs:range . + + +### http://www.w3.org/ns/lemon/termlex#functionalIsLexicalizedSenseOf +:functionalIsLexicalizedSenseOf rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf ; + owl:inverseOf :functionalLexicalizedSense . + + +### http://www.w3.org/ns/lemon/termlex#functionalLexicalizedSense +:functionalLexicalizedSense rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf ; + rdf:type owl:FunctionalProperty ; + rdfs:domain ; + rdfs:range . + + +### http://www.w3.org/ns/lemon/termlex#functionalTermContext +:functionalTermContext rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf ; + owl:inverseOf :isFunctionalTermContextOf ; + rdfs:domain ; + rdfs:range :TermContext . + + +### http://www.w3.org/ns/lemon/termlex#isFunctionalTermContextOf +:isFunctionalTermContextOf rdf:type owl:ObjectProperty ; + rdfs:subPropertyOf . + + +### http://www.w3.org/ns/lemon/termlex#isReliabilityCodeOf +:isReliabilityCodeOf rdf:type owl:ObjectProperty ; + owl:inverseOf :reliabilityCode . + + +### http://www.w3.org/ns/lemon/termlex#isTermUsageOf +:isTermUsageOf rdf:type owl:ObjectProperty ; + owl:inverseOf :termUsage . + + +### http://www.w3.org/ns/lemon/termlex#reliabilityCode +:reliabilityCode rdf:type owl:ObjectProperty ; + rdfs:domain ; + rdfs:range :ReliabilityCode . + + +### http://www.w3.org/ns/lemon/termlex#termUsage +:termUsage rdf:type owl:ObjectProperty ; + rdfs:domain ; + rdfs:range :TermUsage . + + +################################################################# +# Data properties +################################################################# + +### http://purl.org/dc/terms/alternative + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/available + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/bibliographicCitation + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/created + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/date + rdf:type owl:DatatypeProperty . + + +### http://purl.org/dc/terms/dateAccepted + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/dateCopyrighted + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/dateSubmitted + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/identifier + rdf:type owl:DatatypeProperty . + + +### http://purl.org/dc/terms/issued + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/modified + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://purl.org/dc/terms/title + rdf:type owl:DatatypeProperty . + + +### http://purl.org/dc/terms/valid + rdf:type owl:DatatypeProperty ; + rdfs:subPropertyOf . + + +### http://www.w3.org/ns/lemon/ontolex#writtenRep + rdf:type owl:DatatypeProperty . + + +################################################################# +# Classes +################################################################# + +### http://purl.org/dc/dcam/VocabularyEncodingScheme + rdf:type owl:Class . + + +### http://purl.org/dc/terms/Agent + rdf:type owl:Class . + + +### http://purl.org/dc/terms/AgentClass + rdf:type owl:Class ; + rdfs:subClassOf rdfs:Class . + + +### http://purl.org/dc/terms/BibliographicResource + rdf:type owl:Class . + + +### http://purl.org/dc/terms/FileFormat + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/Frequency + rdf:type owl:Class . + + +### http://purl.org/dc/terms/Jurisdiction + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/LicenseDocument + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/LinguisticSystem + rdf:type owl:Class . + + +### http://purl.org/dc/terms/Location + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/LocationPeriodOrJurisdiction + rdf:type owl:Class . + + +### http://purl.org/dc/terms/MediaType + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/MediaTypeOrExtent + rdf:type owl:Class . + + +### http://purl.org/dc/terms/MethodOfAccrual + rdf:type owl:Class . + + +### http://purl.org/dc/terms/MethodOfInstruction + rdf:type owl:Class . + + +### http://purl.org/dc/terms/PeriodOfTime + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/PhysicalMedium + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/PhysicalResource + rdf:type owl:Class . + + +### http://purl.org/dc/terms/Policy + rdf:type owl:Class . + + +### http://purl.org/dc/terms/ProvenanceStatement + rdf:type owl:Class . + + +### http://purl.org/dc/terms/RightsStatement + rdf:type owl:Class . + + +### http://purl.org/dc/terms/SizeOrDuration + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://purl.org/dc/terms/Standard + rdf:type owl:Class . + + +### http://www.w3.org/2004/02/skos/core#Concept + rdf:type owl:Class . + + +### http://www.w3.org/2004/02/skos/core#ConceptScheme + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/lexicog#UsageExample + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/lime#Lexicon + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/ontolex#Form + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/ontolex#LexicalConcept + rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://www.w3.org/ns/lemon/ontolex#LexicalEntry + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/ontolex#LexicalSense + rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#Definition +:Definition rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#IATE_1443648 +:IATE_1443648 rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#LexicographicalDefinition +:LexicographicalDefinition rdf:type owl:Class ; + rdfs:subClassOf :Definition . + + +### http://www.w3.org/ns/lemon/termlex#Note +:Note rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#ReliabilityCode +:ReliabilityCode rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#Source +:Source rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#TermContext +:TermContext rdf:type owl:Class ; + rdfs:subClassOf . + + +### http://www.w3.org/ns/lemon/termlex#TermUsage +:TermUsage rdf:type owl:Class . + + +### http://www.w3.org/ns/lemon/termlex#TerminologicalDefinition +:TerminologicalDefinition rdf:type owl:Class ; + rdfs:subClassOf :Definition . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1 + rdf:type owl:Class ; + rdfs:subClassOf :IATE_1443648 . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC2 + rdf:type owl:Class ; + rdfs:subClassOf :IATE_1443648 . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC3 + rdf:type owl:Class ; + rdfs:subClassOf :IATE_1443648 . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC4 + rdf:type owl:Class ; + rdfs:subClassOf :IATE_1443648 . + + +################################################################# +# Individuals +################################################################# + +### http://purl.org/dc/terms/ + rdf:type owl:NamedIndividual ; + "2012-06-14"^^xsd:date ; + ; + "DCMI Metadata Terms - other"@en . + + +### http://purl.org/dc/terms/Agent + rdf:type owl:NamedIndividual , + . + + +### http://purl.org/dc/terms/AgentClass + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/BibliographicResource + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Box + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/DCMIType + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of classes specified by the DCMI Type Vocabulary, used to categorize the nature or genre of the resource."@en ; + rdfs:isDefinedBy ; + rdfs:label "DCMI Type Vocabulary"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/DDC + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of conceptual resources specified by the Dewey Decimal Classification."@en ; + rdfs:isDefinedBy ; + rdfs:label "DDC"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/FileFormat + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Frequency + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/IMT + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of media types specified by the Internet Assigned Numbers Authority."@en ; + rdfs:isDefinedBy ; + rdfs:label "IMT"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/ISO3166 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/ISO639-2 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/ISO639-3 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Jurisdiction + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/LCC + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of conceptual resources specified by the Library of Congress Classification."@en ; + rdfs:isDefinedBy ; + rdfs:label "LCC"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/LCSH + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of labeled concepts specified by the Library of Congress Subject Headings."@en ; + rdfs:isDefinedBy ; + rdfs:label "LCSH"@en . + + +### http://purl.org/dc/terms/LicenseDocument + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/LinguisticSystem + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Location + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/LocationPeriodOrJurisdiction + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/MESH + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of labeled concepts specified by the Medical Subject Headings."@en ; + rdfs:isDefinedBy ; + rdfs:label "MeSH"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/MediaType + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/MediaTypeOrExtent + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/MethodOfAccrual + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/MethodOfInstruction + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/NLM + rdf:type owl:NamedIndividual , + ; + "2005-06-13"^^xsd:date ; + rdfs:comment "The set of conceptual resources specified by the National Library of Medicine Classification."@en ; + rdfs:isDefinedBy ; + rdfs:label "NLM"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/Period + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/PeriodOfTime + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/PhysicalMedium + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/PhysicalResource + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Point + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Policy + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/ProvenanceStatement + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/RFC1766 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/RFC3066 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/RFC4646 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/RFC5646 + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/RightsStatement + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/SizeOrDuration + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/Standard + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/TGN + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of places specified by the Getty Thesaurus of Geographic Names."@en ; + rdfs:isDefinedBy ; + rdfs:label "TGN"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/UDC + rdf:type owl:NamedIndividual , + ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of conceptual resources specified by the Universal Decimal Classification."@en ; + rdfs:isDefinedBy ; + rdfs:label "UDC"@en ; + rdfs:seeAlso . + + +### http://purl.org/dc/terms/URI + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/W3CDTF + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/abstract + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/accessRights + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/accrualMethod + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/accrualPeriodicity + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/accrualPolicy + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/alternative + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/audience + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/available + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/bibliographicCitation + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/conformsTo + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/contributor + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/coverage + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/created + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/creator + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/date + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/dateAccepted + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/dateCopyrighted + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/dateSubmitted + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/description + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/educationLevel + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/extent + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/format + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/hasFormat + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/hasPart + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/hasVersion + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/identifier + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/instructionalMethod + rdf:type owl:NamedIndividual ; + ; + "Instructional Method typically includes ways of presenting instructional materials or conducting instructional activities, patterns of learner-to-learner and learner-to-instructor interactions, and mechanisms by which group and individual levels of learning are measured. Instructional methods include all aspects of the instruction and learning processes from planning and implementation through evaluation and feedback."@en ; + "2005-06-13"^^xsd:date ; + rdfs:comment "A process, used to engender knowledge, attitudes and skills, that the described resource is designed to support."@en ; + rdfs:isDefinedBy ; + rdfs:label "Instructional Method"@en . + + +### http://purl.org/dc/terms/isFormatOf + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/isPartOf + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/isReferencedBy + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/isReplacedBy + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/isRequiredBy + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/isVersionOf + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/issued + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/language + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/license + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/mediator + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/medium + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/modified + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/provenance + rdf:type owl:NamedIndividual ; + ; + "The statement may include a description of any changes successive custodians made to the resource."@en ; + "2004-09-20"^^xsd:date ; + rdfs:comment "A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity, and interpretation."@en ; + rdfs:isDefinedBy ; + rdfs:label "Provenance"@en . + + +### http://purl.org/dc/terms/publisher + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/references + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/relation + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/replaces + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/requires + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/rights + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/rightsHolder + rdf:type owl:NamedIndividual ; + ; + "Recommended practice is to refer to the rights holder with a URI. If this is not possible or feasible, a literal value that identifies the rights holder may be provided."@en ; + "2004-06-14"^^xsd:date ; + rdfs:comment "A person or organization owning or managing rights over the resource."@en ; + rdfs:isDefinedBy ; + rdfs:label "Rights Holder"@en . + + +### http://purl.org/dc/terms/source + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/spatial + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/subject + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/tableOfContents + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/temporal + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/title + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/type + rdf:type owl:NamedIndividual . + + +### http://purl.org/dc/terms/valid + rdf:type owl:NamedIndividual . + + +### http://www.w3.org/ns/lemon/termlex#Deprecated +:Deprecated rdf:type owl:NamedIndividual , + :TermUsage . + + +### http://www.w3.org/ns/lemon/termlex#IATE_1443648 +:IATE_1443648 rdf:type owl:NamedIndividual , + ; + :transport_terms . + + +### http://www.w3.org/ns/lemon/termlex#Permitted +:Permitted rdf:type owl:NamedIndividual , + :TermUsage . + + +### http://www.w3.org/ns/lemon/termlex#Preferred +:Preferred rdf:type owl:NamedIndividual , + :TermUsage . + + +### http://www.w3.org/ns/lemon/termlex#en_lexicon +:en_lexicon rdf:type owl:NamedIndividual , + ; + , + . + + +### http://www.w3.org/ns/lemon/termlex#es_lexicon +:es_lexicon rdf:type owl:NamedIndividual , + ; + , + ; + "es"@es . + + +### http://www.w3.org/ns/lemon/termlex#transport_terms +:transport_terms rdf:type owl:NamedIndividual , + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1 + rdf:type owl:NamedIndividual , + ; + :functionalIsEvokedBy ; + :functionalLexicalizedSense ; + :functionalTermContext ; + :termUsage :Preferred . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1_2_TDEF + rdf:type owl:NamedIndividual , + :TerminologicalDefinition ; + ; + rdf:value "capacidad de infraestructura necesaria para que un tren circule entre dos puntos en un momento dado"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1_LEN1 + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1_LS + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC1_TC + rdf:type owl:NamedIndividual , + :TermContext ; + ; + rdf:value "Un surco ferroviario es, por tanto, el derecho que el ADIF concede a un operador determinado, para explotar un tramo de vía determinado en un día, hora y sentido determinados. A partir de aquí, resulta fácil imaginar que la competencia entre los operadores que entren en el negocio consistirá fundamentalmente en la obtención de cuántos más surcos mejor."@es . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC2 + rdf:type owl:NamedIndividual , + ; + :definition ; + :functionalIsEvokedBy ; + :functionalLexicalizedSense ; + :functionalTermContext ; + :termUsage :Deprecated . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC2_LEN1 + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC2_LS + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC2_TC + rdf:type owl:NamedIndividual , + :TermContext ; + ; + rdf:value "Capacidad de infraestructura: la capacidad para programar las franjas ferroviarias solicitadas para un segmento de la infraestructura durante un periodo determinado."@es . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC3 + rdf:type owl:NamedIndividual , + ; + :functionalIsEvokedBy ; + :functionalLexicalizedSense ; + :functionalTermContext ; + :termUsage :Preferred . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC3_LEN1 + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC3_LS + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC3_TC + rdf:type owl:NamedIndividual , + :TermContext ; + ; + rdf:value """Access planning is a general description of the process that translates customer requirements for access to the network into detailed plans for the provision of safe and reliable train paths or engineering access plans. +... +Our goal is to implement an efficient and effective operational planning process, with three key components: +- ... +- annual access planning which produces the “permanent” timetable, published as the National Rail Timetable (NRT), which provides a sound basis for delivering train paths safely and reliably; and +- ... +... +Once a valid and operable train path has been identified that best meets the potential operator’s aspirations the operator is able to make an application to the Office of Rail Regulation (ORR) for appropriate access rights."""@en . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC4 + rdf:type owl:NamedIndividual , + ; + :functionalIsEvokedBy ; + :functionalLexicalizedSense ; + :functionalTermContext . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC4_LEN1 + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC4_LS + rdf:type owl:NamedIndividual , + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LC4_TC + rdf:type owl:NamedIndividual , + :TermContext ; + ; + rdf:value "A train operator’s train slots are protected insofar as they are based on firm rights, which are not inconsistent with the applicable Rules of the Route and/or Rules of the Plan, provided that the firm rights have been asserted no later than the Priority Date."@en . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LEN1_F1 + rdf:type owl:NamedIndividual , + ; + "surco ferroviario"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LEN2_F1 + rdf:type owl:NamedIndividual , + ; + "franja ferroviaria"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LEN3_F1 + rdf:type owl:NamedIndividual , + ; + "train path"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LEN4_F1 + rdf:type owl:NamedIndividual , + ; + "train slot"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443648_LS1_LS3_SR1 + rdf:type owl:NamedIndividual , + ; + ; + . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC1_2_TDEF_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "CELEX:32001L0014/ES"^^ ; + rdf:value "Directiva 2001/14/CE relativa a la adjudicación de la capacidad de infraestructura ferroviaria y la aplicación de cánones por su utilización"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC1_NT1 + rdf:type owl:NamedIndividual , + :Note ; + "https://iate.europa.eu/search/result/1626968015909/1"^^xsd:anyURI ; + rdf:value "Se trata de unidades cuya disponibilidad depende de factores como el número de vías disponibles, el sistema de señalización o la diferencia de velocidad entre trenes. El Administrador de Infraestructuras Ferroviarias (Adif) concede a los operadores el derecho de explotar un tramo de vía en un día, una hora y un sentido determinado."@es . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC1_TC_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "http://www.cel-logistica.org/subidasArticulos/90.pdf"^^ ; + rdf:value "Hacia la liberalización efectiva del ferrocarril, Miquel Llevat, Director General de Comsa Rail"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC2_TC_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "http://www.fomento.es/NR/rdonlyres/432E286F-0172-4227-95DC-FA8F7B5F776C/12102/leysectorferroviario.pdf"^^ ; + rdf:value "Ley 39/2003, de 17 de noviembre, del Sector Ferroviario ( [nov-2009])"@es . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC3_4_TDEF + rdf:type owl:NamedIndividual , + :TerminologicalDefinition ; + ; + rdf:value "infrastructure capacity needed to run a train between two places over a given time-period"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC3_4_TDEF_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CONSLEG:2001L0014:20071204:EN:PDF"^^ ; + rdf:value "Article 2(l) of Directive 2001/14/EC on the allocation of railway infrastructure capacity and the levying of charges for the use of railway infrastructure"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC3_TC_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "http://www.networkrail.co.uk/browse%20documents/Restricted/Documents/NetworkStatment/AnnexA.doc"^^ ; + rdf:value "UK > Network Rail > The 2011 Network Statement > Annex A – Access Planning Code of Practice,"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LC4_TC_SRC1 + rdf:type owl:NamedIndividual , + :Source ; + "http://businessdocbox.com/Logistics/69977490-Review-of-rail-cross-industry-interfaces-incentives-and-structures.html" ; + rdf:value "Review of rail cross-industry interfaces, incentives, and structures — Options to reduce industry net cost. Prepared for Value for Money (VfM) Review team, September 30th 2010,"@en . + + +### http://www.w3.org/ns/lemon/termlex#1443680_LS1_LS2_SR1 + rdf:type owl:NamedIndividual , + . + + +################################################################# +# Annotations +################################################################# + + rdfs:label "Agent"@en ; + rdfs:comment "A resource that acts or has the power to act."@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date . + + + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:label "Agent Class"@en ; + rdfs:comment "A group of agents."@en . + + + rdfs:isDefinedBy ; + rdfs:comment "A book, article, or other documentary resource."@en ; + rdfs:label "Bibliographic Resource"@en ; + "2008-01-14"^^xsd:date . + + + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of regions in space defined by their geographic coordinates according to the DCMI Box Encoding Scheme."@en ; + rdfs:isDefinedBy ; + rdfs:label "DCMI Box"@en ; + rdfs:seeAlso . + + + rdfs:comment "A digital resource format."@en ; + rdfs:label "File Format"@en ; + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy . + + + rdfs:label "Frequency"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A rate at which something recurs."@en ; + "2008-01-14"^^xsd:date . + + + rdfs:comment "The set of codes listed in ISO 3166-1 for the representation of names of countries."@en ; + "2000-07-11"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:label "ISO 3166"@en ; + rdfs:seeAlso . + + + rdfs:seeAlso ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The three-letter alphabetic codes listed in ISO639-2 for the representation of names of languages."@en ; + rdfs:isDefinedBy ; + rdfs:label "ISO 639-2"@en . + + + rdfs:comment "The set of three-letter codes listed in ISO 639-3 for the representation of names of languages."@en ; + rdfs:label "ISO 639-3"@en ; + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:seeAlso . + + + rdfs:label "Jurisdiction"@en ; + rdfs:comment "The extent or range of judicial, law enforcement, or other authority."@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:label "License Document"@en ; + "2008-01-14"^^xsd:date ; + rdfs:comment "A legal document giving official permission to do something with a resource."@en . + + + "2008-01-14"^^xsd:date ; + "Written, spoken, sign, and computer languages are linguistic systems."@en ; + rdfs:isDefinedBy ; + rdfs:comment "A system of signs, symbols, sounds, gestures, or rules used in communication."@en ; + rdfs:label "Linguistic System"@en . + + + "2008-01-14"^^xsd:date ; + rdfs:label "Location"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A spatial region or named place."@en . + + + rdfs:label "Location, Period, or Jurisdiction"@en ; + "2008-01-14"^^xsd:date ; + rdfs:comment "A location, period of time, or jurisdiction."@en ; + rdfs:isDefinedBy . + + + rdfs:comment "A file format or physical medium."@en ; + rdfs:isDefinedBy ; + rdfs:label "Media Type"@en ; + "2008-01-14"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:comment "A media type or extent."@en ; + rdfs:label "Media Type or Extent"@en ; + "2008-01-14"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:comment "A method by which resources are added to a collection."@en ; + rdfs:label "Method of Accrual"@en ; + "2008-01-14"^^xsd:date . + + + rdfs:label "Method of Instruction"@en ; + rdfs:comment "A process that is used to engender knowledge, attitudes, and skills."@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date . + + + rdfs:seeAlso ; + rdfs:comment "The set of time intervals defined by their limits according to the DCMI Period Encoding Scheme."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "DCMI Period"@en ; + rdfs:isDefinedBy . + + + rdfs:comment "An interval of time that is named or defined by its start and end dates."@en ; + rdfs:isDefinedBy ; + rdfs:label "Period of Time"@en ; + "2008-01-14"^^xsd:date . + + + "2008-01-14"^^xsd:date ; + "Examples include paper, canvas, or DVD."@en ; + rdfs:label "Physical Medium"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A physical material or carrier."@en . + + + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:comment "A material thing."@en ; + rdfs:label "Physical Resource"@en . + + + rdfs:comment "The set of points in space defined by their geographic coordinates according to the DCMI Point Encoding Scheme."@en ; + rdfs:label "DCMI Point"@en ; + "2000-07-11"^^xsd:date ; + rdfs:seeAlso ; + rdfs:isDefinedBy . + + + rdfs:label "Policy"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A plan or course of action by an authority, intended to influence and determine decisions, actions, and other matters."@en ; + "2008-01-14"^^xsd:date . + + + rdfs:label "Provenance Statement"@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date ; + rdfs:comment "Any changes in ownership and custody of a resource since its creation that are significant for its authenticity, integrity, and interpretation."@en . + + + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date ; + rdfs:comment "The set of tags, constructed according to RFC 1766, for the identification of languages."@en ; + rdfs:seeAlso ; + rdfs:label "RFC 1766"@en . + + + "2002-07-13"^^xsd:date ; + rdfs:label "RFC 3066"@en ; + rdfs:isDefinedBy ; + "RFC 3066 has been obsoleted by RFC 4646."@en ; + rdfs:comment "The set of tags constructed according to RFC 3066 for the identification of languages."@en ; + rdfs:seeAlso . + + + "RFC 4646 obsoletes RFC 3066."@en ; + "2008-01-14"^^xsd:date ; + rdfs:seeAlso ; + rdfs:isDefinedBy ; + rdfs:comment "The set of tags constructed according to RFC 4646 for the identification of languages."@en ; + rdfs:label "RFC 4646"@en . + + + "2010-10-11"^^xsd:date ; + rdfs:seeAlso ; + rdfs:comment "The set of tags constructed according to RFC 5646 for the identification of languages."@en ; + rdfs:label "RFC 5646"@en ; + "RFC 5646 obsoletes RFC 4646."@en ; + rdfs:isDefinedBy . + + + rdfs:label "Rights Statement"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A statement about the intellectual property rights (IPR) held in or over a resource, a legal document giving official permission to do something with a resource, or a statement about access rights."@en ; + "2008-01-14"^^xsd:date . + + + rdfs:label "Size or Duration"@en ; + "Examples include a number of pages, a specification of length, width, and breadth, or a period in hours, minutes, and seconds."@en ; + rdfs:comment "A dimension or extent, or a time taken to play or execute."@en ; + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy . + + + rdfs:comment "A reference point against which other things can be evaluated or compared."@en ; + rdfs:label "Standard"@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:comment "The set of identifiers constructed according to the generic syntax for Uniform Resource Identifiers as specified by the Internet Engineering Task Force."@en ; + "2000-07-11"^^xsd:date ; + rdfs:seeAlso ; + rdfs:label "URI"@en . + + + rdfs:label "W3C-DTF"@en ; + rdfs:comment "The set of dates and times constructed according to the W3C Date and Time Formats Specification."@en ; + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date ; + rdfs:seeAlso . + + + rdfs:label "Abstract"@en ; + "2000-07-11"^^xsd:date ; + rdfs:comment "A summary of the resource."@en ; + rdfs:isDefinedBy . + + + "Access Rights may include information regarding access or restrictions based on privacy, security, or other policies."@en ; + "2003-02-15"^^xsd:date ; + rdfs:comment "Information about who access the resource or an indication of its security status."@en ; + rdfs:label "Access Rights"@en ; + ; + rdfs:isDefinedBy . + + + rdfs:label "Accrual Method"@en ; + "Recommended practice is to use a value from the Collection Description Accrual Method Vocabulary [[DCMI-ACCRUALMETHOD](https://dublincore.org/groups/collections/accrual-method/)]."@en ; + rdfs:comment "The method by which items are added to a collection."@en ; + ; + rdfs:isDefinedBy ; + "2005-06-13"^^xsd:date . + + + "Recommended practice is to use a value from the Collection Description Frequency Vocabulary [[DCMI-COLLFREQ](https://dublincore.org/groups/collections/frequency/)]."@en ; + rdfs:label "Accrual Periodicity"@en ; + rdfs:comment "The frequency with which items are added to a collection."@en ; + rdfs:isDefinedBy ; + "2005-06-13"^^xsd:date ; + . + + + rdfs:isDefinedBy ; + "Recommended practice is to use a value from the Collection Description Accrual Policy Vocabulary [[DCMI-ACCRUALPOLICY](https://dublincore.org/groups/collections/accrual-policy/)]."@en ; + "2005-06-13"^^xsd:date ; + ; + rdfs:comment "The policy governing the addition of items to a collection."@en ; + rdfs:label "Accrual Policy"@en . + + + rdfs:comment "An alternative name for the resource."@en ; + rdfs:isDefinedBy ; + "The distinction between titles and alternative titles is application-specific."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "Alternative Title"@en . + + + "2001-05-21"^^xsd:date ; + rdfs:label "Audience"@en ; + rdfs:isDefinedBy ; + "Recommended practice is to use this property with non-literal values from a vocabulary of audience types."@en ; + rdfs:comment "A class of agents for whom the resource is intended or useful."@en ; + . + + + rdfs:isDefinedBy ; + rdfs:label "Date Available"@en ; + rdfs:comment "Date that the resource became or will become available."@en ; + "2000-07-11"^^xsd:date ; + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en . + + + "Recommended practice is to include sufficient bibliographic detail to identify the resource as unambiguously as possible."@en ; + rdfs:label "Bibliographic Citation"@en ; + rdfs:comment "A bibliographic reference for the resource."@en ; + rdfs:isDefinedBy ; + "2003-02-15"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:label "Conforms To"@en ; + rdfs:comment "An established standard to which the described resource conforms."@en ; + ; + "2001-05-21"^^xsd:date . + + + rdfs:comment "An entity responsible for making contributions to the resource."@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date ; + ; + rdfs:label "Contributor"@en ; + "The guidelines for using names of persons or organizations as creators apply to contributors."@en . + + + ; + rdfs:isDefinedBy ; + rdfs:comment "The spatial or temporal topic of the resource, spatial applicability of the resource, or jurisdiction under which the resource is relevant."@en ; + ; + rdfs:label "Coverage"@en ; + "2008-01-14"^^xsd:date ; + "Spatial topic and spatial applicability may be a named place or a location specified by its geographic coordinates. Temporal topic may be a named period, date, or date range. A jurisdiction may be a named administrative entity or a geographic place to which the resource applies. Recommended practice is to use a controlled vocabulary such as the Getty Thesaurus of Geographic Names [[TGN](https://www.getty.edu/research/tools/vocabulary/tgn/index.html)]. Where appropriate, named places or time periods may be used in preference to numeric identifiers such as sets of coordinates or date ranges. Because coverage is so broadly defined, it is preferable to use the more specific subproperties Temporal Coverage and Spatial Coverage."@en ; + . + + + rdfs:isDefinedBy ; + rdfs:comment "Date of creation of the resource."@en ; + rdfs:label "Date Created"@en ; + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; + "2000-07-11"^^xsd:date . + + + ; + rdfs:isDefinedBy ; + "Recommended practice is to identify the creator with a URI. If this is not possible or feasible, a literal value that identifies the creator may be provided."@en ; + rdfs:comment "An entity responsible for making the resource."@en ; + "2008-01-14"^^xsd:date ; + rdfs:label "Creator"@en . + + + rdfs:isDefinedBy ; + rdfs:comment "A point or period of time associated with an event in the lifecycle of the resource."@en ; + "2008-01-14"^^xsd:date ; + rdfs:label "Date"@en ; + "Date may be used to express temporal information at any level of granularity. Recommended practice is to express the date, date/time, or period of time according to ISO 8601-1 [[ISO 8601-1](https://www.iso.org/iso-8601-date-and-time-format.html)] or a published profile of the ISO standard, such as the W3C Note on Date and Time Formats [[W3CDTF](https://www.w3.org/TR/NOTE-datetime)] or the Extended Date/Time Format Specification [[EDTF](http://www.loc.gov/standards/datetime/)]. If the full date is unknown, month and year (YYYY-MM) or just year (YYYY) may be used. Date ranges may be specified using ISO 8601 period of time specification in which start and end dates are separated by a '/' (slash) character. Either the start or end date may be missing."@en . + + + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty. Examples of resources to which a date of acceptance may be relevant are a thesis (accepted by a university department) or an article (accepted by a journal)."@en ; + "2002-07-13"^^xsd:date ; + rdfs:comment "Date of acceptance of the resource."@en ; + rdfs:label "Date Accepted"@en ; + rdfs:isDefinedBy . + + + rdfs:isDefinedBy ; + rdfs:label "Date Copyrighted"@en ; + rdfs:comment "Date of copyright of the resource."@en ; + "Typically a year. Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; + "2002-07-13"^^xsd:date . + + + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty. Examples of resources to which a 'Date Submitted' may be relevant include a thesis (submitted to a university department) or an article (submitted to a journal)."@en ; + rdfs:comment "Date of submission of the resource."@en ; + "2002-07-13"^^xsd:date ; + rdfs:label "Date Submitted"@en ; + rdfs:isDefinedBy . + + + rdfs:label "Description"@en ; + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date ; + rdfs:comment "An account of the resource."@en ; + "Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."@en . + + + ; + rdfs:comment "A class of agents, defined in terms of progression through an educational or training context, for which the described resource is intended."@en ; + rdfs:isDefinedBy ; + rdfs:label "Audience Education Level"@en ; + "2002-07-13"^^xsd:date . + + + "Recommended practice is to specify the file size in megabytes and duration in ISO 8601 format."@en ; + ; + "2000-07-11"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:comment "The size or duration of the resource."@en ; + rdfs:label "Extent"@en . + + + "2008-01-14"^^xsd:date ; + rdfs:comment "The file format, physical medium, or dimensions of the resource."@en ; + , + ; + "Recommended practice is to use a controlled vocabulary where available. For example, for file formats one could use the list of Internet Media Types [[MIME](https://www.iana.org/assignments/media-types/media-types.xhtml)]. Examples of dimensions include size and duration."@en ; + rdfs:isDefinedBy ; + rdfs:label "Format"@en . + + + rdfs:isDefinedBy ; + "This property is intended to be used with non-literal values. This property is an inverse property of Is Format Of."@en ; + rdfs:label "Has Format"@en ; + "2000-07-11"^^xsd:date ; + rdfs:comment "A related resource that is substantially the same as the pre-existing described resource, but in another format."@en . + + + rdfs:isDefinedBy ; + "This property is intended to be used with non-literal values. This property is an inverse property of Is Part Of."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "Has Part"@en ; + rdfs:comment "A related resource that is included either physically or logically in the described resource."@en . + + + rdfs:comment "A related resource that is a version, edition, or adaptation of the described resource."@en ; + rdfs:isDefinedBy ; + rdfs:label "Has Version"@en ; + "Changes in version imply substantive changes in content rather than differences in format. This property is intended to be used with non-literal values. This property is an inverse property of Is Version Of."@en ; + "2000-07-11"^^xsd:date . + + + rdfs:isDefinedBy ; + "Recommended practice is to identify the resource by means of a string conforming to an identification system. Examples include International Standard Book Number (ISBN), Digital Object Identifier (DOI), and Uniform Resource Name (URN). Persistent identifiers should be provided as HTTP URIs."@en ; + rdfs:comment "An unambiguous reference to the resource within a given context."@en ; + rdfs:label "Identifier"@en ; + "2008-01-14"^^xsd:date . + + + rdfs:comment "A pre-existing related resource that is substantially the same as the described resource, but in another format."@en ; + "This property is intended to be used with non-literal values. This property is an inverse property of Has Format."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "Is Format Of"@en ; + rdfs:isDefinedBy . + + + rdfs:label "Is Part Of"@en ; + "2000-07-11"^^xsd:date ; + "This property is intended to be used with non-literal values. This property is an inverse property of Has Part."@en ; + rdfs:isDefinedBy ; + rdfs:comment "A related resource in which the described resource is physically or logically included."@en . + + + "This property is intended to be used with non-literal values. This property is an inverse property of References."@en ; + rdfs:label "Is Referenced By"@en ; + rdfs:comment "A related resource that references, cites, or otherwise points to the described resource."@en ; + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:label "Is Replaced By"@en ; + "This property is intended to be used with non-literal values. This property is an inverse property of Replaces."@en ; + rdfs:comment "A related resource that supplants, displaces, or supersedes the described resource."@en ; + "2000-07-11"^^xsd:date . + + + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date ; + rdfs:label "Is Required By"@en ; + "This property is intended to be used with non-literal values. This property is an inverse property of Requires."@en ; + rdfs:comment "A related resource that requires the described resource to support its function, delivery, or coherence."@en . + + + rdfs:label "Is Version Of"@en ; + rdfs:isDefinedBy ; + rdfs:comment "A related resource of which the described resource is a version, edition, or adaptation."@en ; + "Changes in version imply substantive changes in content rather than differences in format. This property is intended to be used with non-literal values. This property is an inverse property of Has Version."@en ; + "2000-07-11"^^xsd:date . + + + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date ; + rdfs:comment "Date of formal issuance of the resource."@en ; + rdfs:label "Date Issued"@en . + + + "Recommended practice is to use either a non-literal value representing a language from a controlled vocabulary such as ISO 639-2 or ISO 639-3, or a literal value consisting of an IETF Best Current Practice 47 [[IETF-BCP47](https://tools.ietf.org/html/bcp47)] language tag."@en ; + rdfs:label "Language"@en ; + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:comment "A language of the resource."@en ; + . + + + "2004-06-14"^^xsd:date ; + "Recommended practice is to identify the license document with a URI. If this is not possible or feasible, a literal value that identifies the license may be provided."@en ; + ; + rdfs:label "License"@en ; + rdfs:comment "A legal document giving official permission to do something with the resource."@en ; + rdfs:isDefinedBy . + + + "In an educational context, a mediator might be a parent, teacher, teaching assistant, or care-giver."@en ; + ; + rdfs:comment "An entity that mediates access to the resource."@en ; + rdfs:isDefinedBy ; + rdfs:label "Mediator"@en ; + "2001-05-21"^^xsd:date . + + + rdfs:isDefinedBy ; + ; + rdfs:label "Medium"@en ; + rdfs:comment "The material or physical carrier of the resource."@en ; + ; + "2000-07-11"^^xsd:date . + + + rdfs:isDefinedBy ; + rdfs:label "Date Modified"@en ; + rdfs:comment "Date on which the resource was changed."@en ; + "2000-07-11"^^xsd:date ; + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en . + + + "2008-01-14"^^xsd:date ; + rdfs:label "Publisher"@en ; + ; + rdfs:isDefinedBy ; + rdfs:comment "An entity responsible for making the resource available."@en . + + + "This property is intended to be used with non-literal values. This property is an inverse property of Is Referenced By."@en ; + rdfs:comment "A related resource that is referenced, cited, or otherwise pointed to by the described resource."@en ; + rdfs:label "References"@en ; + "2000-07-11"^^xsd:date ; + rdfs:isDefinedBy . + + + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy ; + "Recommended practice is to identify the related resource by means of a URI. If this is not possible or feasible, a string conforming to a formal identification system may be provided."@en ; + rdfs:label "Relation"@en ; + rdfs:comment "A related resource."@en . + + + "This property is intended to be used with non-literal values. This property is an inverse property of Is Replaced By."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "Replaces"@en ; + rdfs:comment "A related resource that is supplanted, displaced, or superseded by the described resource."@en ; + rdfs:isDefinedBy . + + + "This property is intended to be used with non-literal values. This property is an inverse property of Is Required By."@en ; + rdfs:label "Requires"@en ; + rdfs:comment "A related resource that is required by the described resource to support its function, delivery, or coherence."@en ; + rdfs:isDefinedBy ; + "2000-07-11"^^xsd:date . + + + rdfs:isDefinedBy ; + "2008-01-14"^^xsd:date ; + rdfs:label "Rights"@en ; + ; + rdfs:comment "Information about rights held in and over the resource."@en ; + "Typically, rights information includes a statement about various property rights associated with the resource, including intellectual property rights. Recommended practice is to refer to a rights statement with a URI. If this is not possible or feasible, a literal value (name, label, or short text) may be provided."@en . + + + rdfs:label "Source"@en ; + "2008-01-14"^^xsd:date ; + "This property is intended to be used with non-literal values. The described resource may be derived from the related resource in whole or in part. Best practice is to identify the related resource by means of a URI or a string conforming to a formal identification system."@en ; + rdfs:isDefinedBy ; + rdfs:comment "A related resource from which the described resource is derived."@en . + + + rdfs:label "Spatial Coverage"@en ; + "2000-07-11"^^xsd:date ; + rdfs:isDefinedBy ; + rdfs:comment "Spatial characteristics of the resource."@en ; + . + + + "2008-01-14"^^xsd:date ; + rdfs:label "Subject"@en ; + rdfs:comment "A topic of the resource."@en ; + "Recommended practice is to refer to the subject with a URI. If this is not possible or feasible, a literal value that identifies the subject may be provided. Both should preferably refer to a subject in a controlled vocabulary."@en ; + rdfs:isDefinedBy . + + + "2000-07-11"^^xsd:date ; + rdfs:comment "A list of subunits of the resource."@en ; + rdfs:isDefinedBy ; + rdfs:label "Table Of Contents"@en . + + + ; + "2000-07-11"^^xsd:date ; + rdfs:label "Temporal Coverage"@en ; + rdfs:comment "Temporal characteristics of the resource."@en ; + rdfs:isDefinedBy . + + + rdfs:label "Title"@en ; + rdfs:comment "A name given to the resource."@en ; + "2008-01-14"^^xsd:date ; + rdfs:isDefinedBy . + + + rdfs:isDefinedBy ; + "Recommended practice is to use a controlled vocabulary such as the DCMI Type Vocabulary [[DCMI-TYPE](http://dublincore.org/documents/dcmi-type-vocabulary/)]. To describe the file format, physical medium, or dimensions of the resource, use the property Format."@en ; + rdfs:comment "The nature or genre of the resource."@en ; + rdfs:label "Type"@en ; + "2008-01-14"^^xsd:date . + + + "Recommended practice is to describe the date, date/time, or period of time as recommended for the property Date, of which this is a subproperty."@en ; + rdfs:comment "Date (often a range) of validity of a resource."@en ; + "2000-07-11"^^xsd:date ; + rdfs:label "Date Valid"@en ; + rdfs:isDefinedBy . + + + ; + :term0001_NT1 . + + + ; + :term0001_NT1 , + "Véase el campo \"Language Usage\" del término surco ferroviario."@es . + + + . + + + . + + + "Translation Category Reference RDF Schema "@en ; + rdfs:comment "Set of categories for linguistic translations, to be used in combination with lemon translation module" . + + + rdfs:label "cultural equivalent"@en ; + rdfs:comment "Typically, the two terms describe entities that are not semantically but pragmatically equivalent, since they describe similar situations in different cultures and languages. E.g., Ecole Normal (FR) -> Teachers college (EN)"@en . + + + rdfs:comment "Typically, the two terms describe semantically equivalent entities that refer to entities that exist in both cultures and languages. E.g., surrogate mother (EN) -> m�re porteuse (FR)"@en ; + rdfs:label "direct equivalent"@en . + + + rdfs:label "lexical equivalent"@en ; + rdfs:comment "It is said of those terms in different languages that usually point to the same entity, but one of them verbalizes the original term by using target language words. E.g., Ecole Normal (FR) -> Normal School (ES)"@en . + + +### Generated by the OWL API (version 4.5.9.2019-02-01T07:24:44Z) https://github.com/owlcs/owlapi diff --git a/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION b/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION new file mode 100644 index 0000000..4d398c5 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION @@ -0,0 +1,63 @@ +Package: tidyverse +Title: Easily Install and Load the 'Tidyverse' +Version: 2.0.0.9000 +Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = c("aut", "cre")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")), + person("Posit Software, PBC", role = c("cph", "fnd")) + ) +Description: The 'tidyverse' is a set of packages that work in harmony + because they share common data representations and 'API' design. This + package is designed to make it easy to install and load multiple + 'tidyverse' packages in a single step. Learn more about the + 'tidyverse' at . +License: MIT + file LICENSE +URL: https://tidyverse.tidyverse.org, + https://github.com/tidyverse/tidyverse +BugReports: https://github.com/tidyverse/tidyverse/issues +Depends: + R (>= 4.0) +Imports: + broom (>= 1.0.5), + cli (>= 3.6.1), + conflicted (>= 1.2.0), + dbplyr (>= 2.4.0), + dplyr (>= 1.1.3), + dtplyr (>= 1.3.1), + forcats (>= 1.0.0), + ggplot2 (>= 3.4.4), + googledrive (>= 2.1.1), + googlesheets4 (>= 1.1.1), + haven (>= 2.5.3), + hms (>= 1.1.3), + httr (>= 1.4.7), + jsonlite (>= 1.8.7), + lubridate (>= 1.9.3), + magrittr (>= 2.0.3), + pillar (>= 1.9.0), + purrr (>= 1.0.2), + ragg (>= 1.2.6), + readr (>= 2.1.4), + readxl (>= 1.4.3), + reprex (>= 2.0.2), + rlang (>= 1.1.1), + rstudioapi (>= 0.15.0), + rvest (>= 1.0.3), + stringr (>= 1.5.0), + tibble (>= 3.2.1), + tidyr (>= 1.3.0), + xml2 (>= 1.3.5) +Suggests: + covr (>= 3.6.1), + feather (>= 0.3.5), + glue (>= 1.6.2), + knitr (>= 1.41), + rmarkdown (>= 2.20), + testthat (>= 3.1.6) +VignetteBuilder: + knitr +Config/Needs/website: tidyverse/tidytemplate +Config/testthat/edition: 3 +Encoding: UTF-8 +RoxygenNote: 7.3.2 \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION 2 b/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION 2 new file mode 100644 index 0000000..4d398c5 --- /dev/null +++ b/src/somef_core/test/test_data/repositories/tidyverse/DESCRIPTION 2 @@ -0,0 +1,63 @@ +Package: tidyverse +Title: Easily Install and Load the 'Tidyverse' +Version: 2.0.0.9000 +Authors@R: c( + person("Hadley", "Wickham", , "hadley@posit.co", role = c("aut", "cre")), + person("Winston", "Chang", role = "aut", + comment = c(ORCID = "0000-0002-1576-2126")), + person("Posit Software, PBC", role = c("cph", "fnd")) + ) +Description: The 'tidyverse' is a set of packages that work in harmony + because they share common data representations and 'API' design. This + package is designed to make it easy to install and load multiple + 'tidyverse' packages in a single step. Learn more about the + 'tidyverse' at . +License: MIT + file LICENSE +URL: https://tidyverse.tidyverse.org, + https://github.com/tidyverse/tidyverse +BugReports: https://github.com/tidyverse/tidyverse/issues +Depends: + R (>= 4.0) +Imports: + broom (>= 1.0.5), + cli (>= 3.6.1), + conflicted (>= 1.2.0), + dbplyr (>= 2.4.0), + dplyr (>= 1.1.3), + dtplyr (>= 1.3.1), + forcats (>= 1.0.0), + ggplot2 (>= 3.4.4), + googledrive (>= 2.1.1), + googlesheets4 (>= 1.1.1), + haven (>= 2.5.3), + hms (>= 1.1.3), + httr (>= 1.4.7), + jsonlite (>= 1.8.7), + lubridate (>= 1.9.3), + magrittr (>= 2.0.3), + pillar (>= 1.9.0), + purrr (>= 1.0.2), + ragg (>= 1.2.6), + readr (>= 2.1.4), + readxl (>= 1.4.3), + reprex (>= 2.0.2), + rlang (>= 1.1.1), + rstudioapi (>= 0.15.0), + rvest (>= 1.0.3), + stringr (>= 1.5.0), + tibble (>= 3.2.1), + tidyr (>= 1.3.0), + xml2 (>= 1.3.5) +Suggests: + covr (>= 3.6.1), + feather (>= 0.3.5), + glue (>= 1.6.2), + knitr (>= 1.41), + rmarkdown (>= 2.20), + testthat (>= 3.1.6) +VignetteBuilder: + knitr +Config/Needs/website: tidyverse/tidytemplate +Config/testthat/edition: 3 +Encoding: UTF-8 +RoxygenNote: 7.3.2 \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/unused/unused 2.cabal b/src/somef_core/test/test_data/repositories/unused/unused 2.cabal new file mode 100644 index 0000000..efbadcb --- /dev/null +++ b/src/somef_core/test/test_data/repositories/unused/unused 2.cabal @@ -0,0 +1,127 @@ +name: unused +version: 0.10.0.0 +synopsis: A command line tool to identify unused code. +description: Please see README.md +homepage: https://github.com/joshuaclayton/unused#readme +license: MIT +license-file: LICENSE +author: Josh Clayton +maintainer: sayhi@joshuaclayton.me +copyright: 2016-2018 Josh Clayton +category: CLI +build-type: Simple +-- extra-source-files: +cabal-version: >=1.10 +data-files: data/config.yml + +library + hs-source-dirs: src + exposed-modules: Unused.TermSearch + , Unused.TermSearch.Types + , Unused.TermSearch.Internal + , Unused.Parser + , Unused.Types + , Unused.GitContext + , Unused.Util + , Unused.Regex + , Unused.Aliases + , Unused.Projection + , Unused.Projection.Transform + , Unused.ResponseFilter + , Unused.ResultsClassifier + , Unused.ResultsClassifier.Types + , Unused.ResultsClassifier.Config + , Unused.Grouping + , Unused.Grouping.Internal + , Unused.Grouping.Types + , Unused.LikelihoodCalculator + , Unused.Cache + , Unused.Cache.DirectoryFingerprint + , Unused.Cache.FindArgsFromIgnoredPaths + , Unused.TagsSource + , Unused.CLI + , Unused.CLI.Search + , Unused.CLI.GitContext + , Unused.CLI.Util + , Unused.CLI.Views + , Unused.CLI.Views.Error + , Unused.CLI.Views.NoResultsFound + , Unused.CLI.Views.AnalysisHeader + , Unused.CLI.Views.GitSHAsHeader + , Unused.CLI.Views.MissingTagsFileError + , Unused.CLI.Views.InvalidConfigError + , Unused.CLI.Views.FingerprintError + , Unused.CLI.Views.SearchResult + , Unused.CLI.Views.SearchResult.ColumnFormatter + , Unused.CLI.Views.SearchResult.Internal + , Unused.CLI.Views.SearchResult.ListResult + , Unused.CLI.Views.SearchResult.TableResult + , Unused.CLI.Views.SearchResult.Types + , Unused.CLI.ProgressIndicator + , Unused.CLI.ProgressIndicator.Internal + , Unused.CLI.ProgressIndicator.Types + , Common + build-depends: base >= 4.7 && < 5 + , process + , containers + , filepath + , directory + , regex-tdfa + , terminal-progress-bar >= 0.1.1.1 && < 0.1.2 + , ansi-terminal + , unix + , parallel-io + , yaml + , bytestring + , text + , unordered-containers + , cassava >= 0.5.1.0 && < 0.6 + , vector + , mtl + , transformers + , megaparsec >= 7.0.5 && < 8 + , inflections >= 0.4.0.3 && < 0.5 + , file-embed + ghc-options: -Wall + default-language: Haskell2010 + default-extensions: OverloadedStrings + +executable unused + hs-source-dirs: app + main-is: Main.hs + ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall + build-depends: base + , unused + , optparse-applicative + , mtl + , transformers + other-modules: App + , Types + default-language: Haskell2010 + +test-suite unused-test + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: Spec.hs + build-depends: base + , unused + , hspec + , containers + , text + other-modules: Unused.ParserSpec + , Unused.ResponseFilterSpec + , Unused.TypesSpec + , Unused.LikelihoodCalculatorSpec + , Unused.Grouping.InternalSpec + , Unused.TermSearch.InternalSpec + , Unused.UtilSpec + , Unused.Cache.FindArgsFromIgnoredPathsSpec + , Unused.AliasesSpec + , Unused.ProjectionSpec + ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall + default-language: Haskell2010 + default-extensions: OverloadedStrings + +source-repository head + type: git + location: https://github.com/joshuaclayton/unused \ No newline at end of file diff --git a/src/somef_core/test/test_data/repositories/unused/unused.cabal b/src/somef_core/test/test_data/repositories/unused/unused.cabal new file mode 100644 index 0000000..efbadcb --- /dev/null +++ b/src/somef_core/test/test_data/repositories/unused/unused.cabal @@ -0,0 +1,127 @@ +name: unused +version: 0.10.0.0 +synopsis: A command line tool to identify unused code. +description: Please see README.md +homepage: https://github.com/joshuaclayton/unused#readme +license: MIT +license-file: LICENSE +author: Josh Clayton +maintainer: sayhi@joshuaclayton.me +copyright: 2016-2018 Josh Clayton +category: CLI +build-type: Simple +-- extra-source-files: +cabal-version: >=1.10 +data-files: data/config.yml + +library + hs-source-dirs: src + exposed-modules: Unused.TermSearch + , Unused.TermSearch.Types + , Unused.TermSearch.Internal + , Unused.Parser + , Unused.Types + , Unused.GitContext + , Unused.Util + , Unused.Regex + , Unused.Aliases + , Unused.Projection + , Unused.Projection.Transform + , Unused.ResponseFilter + , Unused.ResultsClassifier + , Unused.ResultsClassifier.Types + , Unused.ResultsClassifier.Config + , Unused.Grouping + , Unused.Grouping.Internal + , Unused.Grouping.Types + , Unused.LikelihoodCalculator + , Unused.Cache + , Unused.Cache.DirectoryFingerprint + , Unused.Cache.FindArgsFromIgnoredPaths + , Unused.TagsSource + , Unused.CLI + , Unused.CLI.Search + , Unused.CLI.GitContext + , Unused.CLI.Util + , Unused.CLI.Views + , Unused.CLI.Views.Error + , Unused.CLI.Views.NoResultsFound + , Unused.CLI.Views.AnalysisHeader + , Unused.CLI.Views.GitSHAsHeader + , Unused.CLI.Views.MissingTagsFileError + , Unused.CLI.Views.InvalidConfigError + , Unused.CLI.Views.FingerprintError + , Unused.CLI.Views.SearchResult + , Unused.CLI.Views.SearchResult.ColumnFormatter + , Unused.CLI.Views.SearchResult.Internal + , Unused.CLI.Views.SearchResult.ListResult + , Unused.CLI.Views.SearchResult.TableResult + , Unused.CLI.Views.SearchResult.Types + , Unused.CLI.ProgressIndicator + , Unused.CLI.ProgressIndicator.Internal + , Unused.CLI.ProgressIndicator.Types + , Common + build-depends: base >= 4.7 && < 5 + , process + , containers + , filepath + , directory + , regex-tdfa + , terminal-progress-bar >= 0.1.1.1 && < 0.1.2 + , ansi-terminal + , unix + , parallel-io + , yaml + , bytestring + , text + , unordered-containers + , cassava >= 0.5.1.0 && < 0.6 + , vector + , mtl + , transformers + , megaparsec >= 7.0.5 && < 8 + , inflections >= 0.4.0.3 && < 0.5 + , file-embed + ghc-options: -Wall + default-language: Haskell2010 + default-extensions: OverloadedStrings + +executable unused + hs-source-dirs: app + main-is: Main.hs + ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall + build-depends: base + , unused + , optparse-applicative + , mtl + , transformers + other-modules: App + , Types + default-language: Haskell2010 + +test-suite unused-test + type: exitcode-stdio-1.0 + hs-source-dirs: test + main-is: Spec.hs + build-depends: base + , unused + , hspec + , containers + , text + other-modules: Unused.ParserSpec + , Unused.ResponseFilterSpec + , Unused.TypesSpec + , Unused.LikelihoodCalculatorSpec + , Unused.Grouping.InternalSpec + , Unused.TermSearch.InternalSpec + , Unused.UtilSpec + , Unused.Cache.FindArgsFromIgnoredPathsSpec + , Unused.AliasesSpec + , Unused.ProjectionSpec + ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall + default-language: Haskell2010 + default-extensions: OverloadedStrings + +source-repository head + type: git + location: https://github.com/joshuaclayton/unused \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-314-2.json b/src/somef_core/test/test_data/test-314-2.json new file mode 100644 index 0000000..32abd70 --- /dev/null +++ b/src/somef_core/test/test_data/test-314-2.json @@ -0,0 +1,83 @@ +{ + "citation": [ + { + "confidence": 1, + "result": { + "original_header": "Citation", + "type": "Text_excerpt", + "value": "```latex\n@inproceedings{\n author = {Julien Leblay and Melisachew Wudage Chekol and Xin Liu},\n title = {Towards Temporal Knowledge Graph Embeddings with Arbitrary Time Precision},\n booktitle = {Proceedings of the 29th {ACM} International Conference on Information and Knowledge Management ({CIKM} '20), October 19--23, 2020, Virtual Event, Ireland},\n publisher = {{ACM}},\n year = {2020},\n url = {https://doi.org/10.1145/3340531.3412028},\n doi = {10.1145/3340531.3412028},\n}\n```\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "ToKEi: Temporal Knowledge Graph Embeddings with Arbitrary Time Precision" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "requirements": [ + { + "confidence": 1, + "result": { + "original_header": "Requirements", + "type": "Text_excerpt", + "value": "The model is implemented in Python 3, using the PyTorch library.\nOther library requirements are listed in `requirements.txt`.\nTo load them into your preference virtual execution environment, use:\n\n pip install -r requirements.txt\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "somef_provenance": { + "date": "2026-01-20 09:30:23", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Pre-training", + "parent_header": [ + "Usage" + ], + "type": "Text_excerpt", + "value": "```\n CUDA_VISIBLE_DEVICES=0 python RotatE/run.py \\\n --cuda \\\n --do_train \\\n --do_valid \\\n --do_test \\\n --data_path data/RotatE/wikidata12k \\\n --model RotatE \\\n -n 256 -b 1024 -d 1000 \\\n -g 24.0 -a 1.0 -adv \\\n -lr 0.0001 --max_steps 150000 \\\n -save models/RotatE_WD12k --test_batch_size 16 -de\n```\nFor a complete list of options, try:\n\n python run.py --help\n\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Training temporal models", + "parent_header": [ + "Usage" + ], + "type": "Text_excerpt", + "value": "```\n CUDA_VISIBLE_DEVICES=0 python train.py \n --seed 0 --data_path data/wikidata12k \\\n -n 128 -b 1024 -p 15000 -wu 5000 \\\n -a 1.0 -lr 0.0001 --max_steps 45000 \\\n -save models/RotatE_WD12k_CDY --test_batch_size 16 \\\n -scope d1100_1_1,d2019_6_30,CDY\n```\nFor more options, try:\n\n python train.py --help\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Testing pre-trained temporal models", + "parent_header": [ + "Usage" + ], + "type": "Text_excerpt", + "value": "```\n CUDA_VISIBLE_DEVICES=0 python test.py \n --data_path data/wikidata12k \\\n -n 128 -b 1024 -p 15000 -wu 5000 \\\n -a 1.0 -lr 0.0001 --max_steps 45000 \\\n -save models/RotatE_WD12k_CDY --test_batch_size 16 \\\n -scope d1100_1_1,d2019_6_30,CDY \\\n\t --test_levels --test_time --test_scoping --test_ranking\n```\n\nFor more options, try:\n\n python test.py --help\n" + }, + "source": null, + "technique": "header_analysis" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-314-3.json b/src/somef_core/test/test_data/test-314-3.json new file mode 100644 index 0000000..31c7758 --- /dev/null +++ b/src/somef_core/test/test_data/test-314-3.json @@ -0,0 +1,133 @@ +{ + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "Adapt - ReactJS for your infrastructure." + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "images": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://adaptjs.org/docs/assets/getting_started/adapt-demo-scaled.gif" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "logo": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://adaptjs.org/img/logo_lockup.svg" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "somef_missing_categories": [ + "application_domain", + "acknowledgement", + "authors", + "citation", + "contributors", + "contributing_guidelines", + "continuous_integration", + "code_of_conduct", + "code_repository", + "contact", + "description", + "date_created", + "date_updated", + "documentation", + "download", + "download_url", + "executable_example", + "faq", + "forks_count", + "forks_url", + "full_name", + "has_build_file", + "has_script_file", + "identifier", + "installation", + "invocation", + "issue_tracker", + "homepage", + "keywords", + "license", + "name", + "ontologies", + "owner", + "package_distribution", + "has_package_file", + "programming_languages", + "readme_url", + "related_documentation", + "releases", + "run", + "runtime_platform", + "related_papers", + "repository_status", + "requirements", + "stargazers_count", + "support_channels", + "workflows", + "type" + ], + "somef_provenance": { + "date": "2026-01-20 09:20:57", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "support": [ + { + "confidence": 1, + "result": { + "original_header": "Getting Help", + "parent_header": [ + "Adapt - ReactJS for your infrastructure." + ], + "type": "Text_excerpt", + "value": "[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt)\n\nWe'd love to hear about your experience with Adapt!\nJoin us on our [Gitter channel](https://gitter.im/UnboundedSystems/Adapt) to ask questions or to give us your feedback and suggestions.\n\nIf you've found a bug, you can also [file an issue](https://gitlab.com/unboundedsystems/adapt/issues).\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Getting Started", + "parent_header": [ + "Adapt - ReactJS for your infrastructure." + ], + "type": "Text_excerpt", + "value": "For a new project, it's easy to get started with Adapt by using a starter template.\nThe [Getting Started Guide](https://adaptjs.org/docs/getting_started) will walk through installing Adapt and deploying your first starter app.\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Getting Help", + "parent_header": [ + "Adapt - ReactJS for your infrastructure." + ], + "type": "Text_excerpt", + "value": "[![Gitter](https://badges.gitter.im/UnboundedSystems/Adapt.svg)](https://gitter.im/UnboundedSystems/Adapt)\n\nWe'd love to hear about your experience with Adapt!\nJoin us on our [Gitter channel](https://gitter.im/UnboundedSystems/Adapt) to ask questions or to give us your feedback and suggestions.\n\nIf you've found a bug, you can also [file an issue](https://gitlab.com/unboundedsystems/adapt/issues).\n" + }, + "source": null, + "technique": "header_analysis" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-379.json b/src/somef_core/test/test_data/test-379.json new file mode 100644 index 0000000..bc6f1af --- /dev/null +++ b/src/somef_core/test/test_data/test-379.json @@ -0,0 +1,96 @@ +{ + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "r.AID.ologist \ud83d\udd8a\ufe0f" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "images": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://i.ibb.co/7Y4ZyhR/Global-Diagram.png" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "installation": [ + { + "confidence": 1, + "result": { + "original_header": "\ud83d\uddb1\ufe0f **Installation**", + "parent_header": [ + "r.AID.ologist \ud83d\udd8a\ufe0f" + ], + "type": "Text_excerpt", + "value": "A ready-to-use version of the framework is available as a Docker image in **elviish/raidologist:latest**. Once downloaded, the image can be ran with the command:\n\n docker run --name raidologist -p *selected_port*:5000 elviish/raidologist:latest\n \nThe framework has been developed using Python 3.7. To locally run the framework, or o modify it, these are the steps to follow:\n\n 1. Clone the repository\n `git clone https://github.com/oeg-upm/AI4EU_raidologist.git`\n \n 2. Install the required dependencies\n `pip install -r requirements.txt`\n \n 3. Install the spacy model\n `python -m spacy download en_core_web_sm`\n \n 4. Download the NER model and place it the directory *externals/i2b2*\n`curl -O https://drive.upm.es/s/gOXyNxXgnrDBIEj/download`\n\n 5. Execute the *main.py* file \n`python main.py`\n\n 6. Go to the direction localhost:5000 in your web browser to start using the framework\n\nIssues can be reported at https://github.com/oeg-upm/AI4EU_raidologist/issues\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "somef_missing_categories": [ + "application_domain", + "acknowledgement", + "authors", + "citation", + "contributors", + "contributing_guidelines", + "continuous_integration", + "code_of_conduct", + "code_repository", + "contact", + "description", + "date_created", + "date_updated", + "documentation", + "download", + "download_url", + "executable_example", + "faq", + "forks_count", + "forks_url", + "full_name", + "has_build_file", + "has_script_file", + "identifier", + "invocation", + "issue_tracker", + "homepage", + "keywords", + "license", + "logo", + "name", + "ontologies", + "owner", + "package_distribution", + "has_package_file", + "programming_languages", + "readme_url", + "related_documentation", + "releases", + "run", + "runtime_platform", + "related_papers", + "repository_status", + "requirements", + "stargazers_count", + "support", + "support_channels", + "usage", + "workflows", + "type" + ], + "somef_provenance": { + "date": "2026-01-20 09:38:17", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + } +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-388.json b/src/somef_core/test/test_data/test-388.json new file mode 100644 index 0000000..2bcdabb --- /dev/null +++ b/src/somef_core/test/test_data/test-388.json @@ -0,0 +1,527 @@ +{ + "citation": [ + { + "confidence": 1, + "result": { + "author": [ + { + "family_name": "Garijo", + "given_name": "Daniel", + "name": "Daniel Garijo", + "type": "Agent", + "url": "http://orcid.org/0000-0003-0454-7145" + } + ], + "datePublished": "2017", + "doi": "10.1007/978-3-319-68204-4_9", + "format": "cff", + "identifier": [ + { + "description": "Collection of archived snapshots for WIDOCO", + "type": "doi", + "value": "10.5281/zenodo.591294" + } + ], + "title": "WIDOCO: A Wizard for documenting ontologies", + "type": "File_dump", + "url": "https://doi.org/10.5281/zenodo.591294", + "value": "title: \"WIDOCO: A Wizard for documenting ontologies\"\nlicense: Apache-2.0\nauthors:\n - family-names: Garijo\n given-names: Daniel\n orcid: \"http://orcid.org/0000-0003-0454-7145\"\ncff-version: 1.2.0\nmessage: \"If you use this software, please cite both the article from preferred-citation and the software itself.\"\npreferred-citation:\n authors:\n - family-names: Garijo\n given-names: Daniel\n title: \"WIDOCO: A wizard for documenting ontologies\"\n type: article\n year: 2017\n doi: 10.1007/978-3-319-68204-4_9\nidentifiers:\n - description: \"Collection of archived snapshots for WIDOCO\"\n type: doi\n value: 10.5281/zenodo.591294\n" + }, + "source": "https://raw.githubusercontent.com/True///CITATION.cff", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "date_published": "2017", + "doi": "10.1007/978-3-319-68204-4_9", + "title": "WIDOCO: a wizard for documenting ontologies", + "type": "Scholarly_article", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "value": "WIDOCO: a wizard for documenting ontologies" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "author": "Garijo, Daniel", + "doi": "10.1007/978-3-319-68204-4_9", + "format": "bibtex", + "title": "WIDOCO: a wizard for documenting ontologies", + "type": "Text_excerpt", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "value": "@inproceedings{garijo2017widoco,\n url = {http://dgarijo.com/papers/widoco-iswc2017.pdf},\n funding = {USNSF ICER-1541029, NIH 1R01GM117097-01},\n doi = {10.1007/978-3-319-68204-4_9},\n organization = {Springer, Cham},\n year = {2017},\n pages = {94--102},\n booktitle = {International Semantic Web Conference},\n author = {Garijo, Daniel},\n title = {WIDOCO: a wizard for documenting ontologies},\n}" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "code_repository": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "contributing_guidelines": [ + { + "confidence": 1, + "result": { + "type": "File_dump", + "value": "## Contribution guidelines\nContributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n" + }, + "source": "https://raw.githubusercontent.com/True///CONTRIBUTING.md", + "technique": "file_exploration" + } + ], + "date_created": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "2013-07-15" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "date_updated": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "2025-01-31" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "description": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + ] + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "original_header": "Description", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html))\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO.\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "documentation": [ + { + "confidence": 1, + "result": { + "original_header": "Browser issues (Why can't I see the generated documentation / visualization?)", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options:\n\n* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the \"load sections\" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally.\n* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers).\n\nIf you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "download": [ + { + "confidence": 1, + "result": { + "original_header": "Downloading the executable", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest).\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "download_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco/releases" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "has_build_file": [ + { + "confidence": 1, + "result": { + "format": "dockerfile", + "type": "Url", + "value": "https://raw.githubusercontent.com/True///Dockerfile" + }, + "source": "https://raw.githubusercontent.com/True///Dockerfile", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "format": "pom.xml", + "type": "Url", + "value": "https://raw.githubusercontent.com/True///pom.xml" + }, + "source": "https://raw.githubusercontent.com/True///pom.xml", + "technique": "file_exploration" + } + ], + "identifier": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "https://doi.org/10.5281/zenodo.11093793" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://zenodo.org/badge/latestdoi/11427075" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "issue_tracker": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco/issues" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "keywords": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": [ + "documentation", + "metadata", + "ontology", + "ontology-diagram", + "ontology-evaluation", + "wizard" + ] + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "license": [ + { + "confidence": 1, + "result": { + "name": "Apache License 2.0", + "spdx_id": "Apache-2.0", + "type": "File_dump", + "value": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {2016} {Daniel Garijo, Information Sciences Institute, USC.}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n" + }, + "source": "https://raw.githubusercontent.com/True///LICENSE", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "identifier": "https://spdx.org/licenses/Apache-2.0", + "spdx_id": "Apache-2.0", + "type": "License", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE", + "value": "Apache License 2.0" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "logo": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "/Users/mbp_jjm/Documents/OEG/WORKSPACE/Somef-core/src/somef_core/test/test_data/repositories/Widoco/src/main/resources/logo/logo2.png" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "Widoco" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "programming_languages": [ + { + "confidence": 1, + "result": { + "name": "JavaScript", + "type": "Programming_language", + "value": "JavaScript" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "Java", + "type": "Programming_language", + "value": "Java" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "XSLT", + "type": "Programming_language", + "value": "XSLT" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "CSS", + "type": "Programming_language", + "value": "CSS" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "HTML", + "type": "Programming_language", + "value": "HTML" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "Dockerfile", + "type": "Programming_language", + "value": "Dockerfile" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "readme_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/True///README.md" + }, + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "type": "String", + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "repository_status": [ + { + "confidence": 1, + "result": { + "description": "Active \u2013 The project has reached a stable, usable state and is being actively developed.", + "type": "Url", + "value": "https://www.repostatus.org/#active" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "requirements": [ + { + "confidence": 1, + "result": { + "type": "Software_application", + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.24\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "type": "Software_application", + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file." + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "original_header": "Importing WIDOCO as a dependency", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.16\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Requirements", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "somef_provenance": { + "date": "2026-01-20 09:38:19", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Examples", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "Examples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/)\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "GUI Tutorial", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "A tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) \n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "JAR execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file.\n\nYou may also execute WIDOCO through the command line. Usage:\n```bash\njava -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS]\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Docker execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "First build the image using the `Dockerfile` in project folder:\n\n```bash\ndocker build -t dgarijo/widoco .\n```\n\nYou can now execute WIDOCO through the command line. Usage:\n\n```bash\ndocker run -ti --rm dgarijo/widoco [OPTIONS]\n```\n\nIf you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container\nwith host directories. For instance:\n\n```bash\ndocker run -ti --rm \\\n -v `pwd`/test:/usr/local/widoco/in \\\n -v `pwd`/target/generated-doc:/usr/local/widoco/out \\\n dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Options", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI\n\n`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile\n\n`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation'\n\n`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata\n\n`-getOntologyMetadata`: Extract ontology metadata from the given ontology\n\n`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/)\n\n`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution)\n\n`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists.\n\n`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology\n\n`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila).\n\n`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by \"-\"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es\n\n`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not.\n\n`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server.\n\n`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation.\n\n`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled.\n\n`-ignoreIndividuals`: Individuals will not be included in the documentation.\n\n`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included)\n\n`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234\n\n`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed.\n\n`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented.\n\n`-rewriteBase PATH`: Change the default rewrite base path. The default value is \"/\". This flag can only be used with the htaccess option.\n\n`-excludeIntroduction`: Skip the introduction section in the documentation.\n\n`-uniteSections`: Write all HTML sections into a single HTML document.\n\n`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections).\n\n`--help`: Shows a help message and exits.\n\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "version": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "v1.4.25" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-428.json b/src/somef_core/test/test_data/test-428.json new file mode 100644 index 0000000..1f95e81 --- /dev/null +++ b/src/somef_core/test/test_data/test-428.json @@ -0,0 +1,187 @@ +{ + "contributing_guidelines": [ + { + "confidence": 1, + "result": { + "original_header": "Contributing", + "type": "Text_excerpt", + "value": "Is always welcome. As mentioned above, the [community edition](https://github.com/ManimCommunity/manim) has the most active ecosystem for contributions, with testing and continuous integration, but pull requests are welcome here too. Please explain the motivation for a given change and examples of its effect.\n\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "documentation": [ + { + "confidence": 1, + "result": { + "original_header": "Documentation", + "parent_header": [ + "Using manim" + ], + "type": "Text_excerpt", + "value": "Documentation is in progress at [3b1b.github.io/manim](https://3b1b.github.io/manim/). And there is also a Chinese version maintained by [**@manim-kindergarten**](https://manim.org.cn): [docs.manim.org.cn](https://docs.manim.org.cn/) (in Chinese).\n\n[manim-kindergarten](https://github.com/manim-kindergarten/) wrote and collected some useful extra classes and some codes of videos in [manim_sandbox repo](https://github.com/manim-kindergarten/manim_sandbox).\n\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "images": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/3b1b/manim/master/logo/cropped.png" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "installation": [ + { + "confidence": 1, + "result": { + "original_header": "Installation", + "type": "Text_excerpt", + "value": "> **WARNING:** These instructions are for ManimGL _only_. Trying to use these instructions to install [ManimCommunity/manim](https://github.com/ManimCommunity/manim) or instructions there to install this version will cause problems. You should first decide which version you wish to install, then only follow the instructions for your desired version.\n> \n> **Note**: To install manim directly through pip, please pay attention to the name of the installed package. This repository is ManimGL of 3b1b. The package name is `manimgl` instead of `manim` or `manimlib`. Please use `pip install manimgl` to install the version in this repository.\n\nManim runs on Python 3.6 or higher (Python 3.8 is recommended).\n\nSystem requirements are [FFmpeg](https://ffmpeg.org/), [OpenGL](https://www.opengl.org/) and [LaTeX](https://www.latex-project.org) (optional, if you want to use LaTeX).\nFor Linux, [Pango](https://pango.gnome.org) along with its development headers are required. See instruction [here](https://github.com/ManimCommunity/ManimPango#building).\n\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Directly", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "```sh\n# Install manimgl\npip install manimgl\n\n# Try it out\nmanimgl\n```\n\nFor more options, take a look at the [Using manim](#using-manim) sections further below.\n\nIf you want to hack on manimlib itself, clone this repository and in that directory execute:\n\n```sh\n# Install manimgl\npip install -e .\n\n# Try it out\nmanimgl example_scenes.py OpeningManimExample\n# or\nmanim-render example_scenes.py OpeningManimExample\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Directly (Windows)", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "1. [Install FFmpeg](https://www.wikihow.com/Install-FFmpeg-on-Windows).\n2. Install a LaTeX distribution. [MiKTeX](https://miktex.org/download) is recommended.\n3. Install the remaining Python packages.\n ```sh\n git clone https://github.com/3b1b/manim.git\n cd manim\n pip install -e .\n manimgl example_scenes.py OpeningManimExample\n ```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Mac OSX", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "1. Install FFmpeg, LaTeX in terminal using homebrew.\n ```sh\n brew install ffmpeg mactex\n ```\n \n2. Install latest version of manim using these command.\n ```sh\n git clone https://github.com/3b1b/manim.git\n cd manim\n pip install -e .\n manimgl example_scenes.py OpeningManimExample\n ```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Anaconda Install", + "type": "Text_excerpt", + "value": "1. Install LaTeX as above.\n2. Create a conda environment using `conda create -n manim python=3.8`.\n3. Activate the environment using `conda activate manim`.\n4. Install manimgl using `pip install -e .`.\n\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "license": [ + { + "confidence": 1, + "result": { + "original_header": "License", + "type": "Text_excerpt", + "value": "This project falls under the MIT license.\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "somef_missing_categories": [ + "application_domain", + "acknowledgement", + "authors", + "citation", + "contributors", + "continuous_integration", + "code_of_conduct", + "code_repository", + "contact", + "description", + "date_created", + "date_updated", + "download", + "download_url", + "executable_example", + "faq", + "forks_count", + "forks_url", + "full_name", + "full_title", + "has_build_file", + "has_script_file", + "identifier", + "invocation", + "issue_tracker", + "homepage", + "keywords", + "logo", + "name", + "ontologies", + "owner", + "package_distribution", + "has_package_file", + "programming_languages", + "readme_url", + "related_documentation", + "releases", + "run", + "runtime_platform", + "related_papers", + "repository_status", + "requirements", + "stargazers_count", + "support", + "usage", + "workflows", + "type" + ], + "somef_provenance": { + "date": "2026-01-20 09:38:32", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "support_channels": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://www.reddit.com/r/manim/" + }, + "source": "README.md", + "technique": "regular_expression" + }, + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://discord.com/invite/bYCyhM9Kz2" + }, + "source": "README.md", + "technique": "regular_expression" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-457.json b/src/somef_core/test/test_data/test-457.json new file mode 100644 index 0000000..eba25a9 --- /dev/null +++ b/src/somef_core/test/test_data/test-457.json @@ -0,0 +1,302 @@ +{ + "contributing_guidelines": [ + { + "confidence": 1, + "result": { + "original_header": "Releases and Contributing", + "type": "Text_excerpt", + "value": "PyTorch has a 90-day release cycle (major releases). Please let us know if you encounter a bug by [filing an issue](https://github.com/pytorch/pytorch/issues).\n\nWe appreciate all contributions. If you are planning to contribute back bug-fixes, please do so without any further discussion.\n\nIf you plan to contribute new features, utility functions, or extensions to the core, please first open an issue and discuss the feature with us.\nSending a PR without discussion might end up resulting in a rejected PR because we might be taking the core in a different direction than you might be aware of.\n\nTo learn more about making a contribution to Pytorch, please see our [Contribution page](CONTRIBUTING.md).\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "documentation": [ + { + "confidence": 1, + "result": { + "original_header": "Building the Documentation", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "To build documentation in various formats, you will need [Sphinx](http://www.sphinx-doc.org) and the\nreadthedocs theme.\n\n```bash\ncd docs/\npip install -r requirements.txt\n```\nYou can then build the documentation by running `make ` from the\n`docs/` folder. Run `make` to get a list of all available output formats.\n\nIf you get a katex error run `npm install katex`. If it persists, try\n`npm install -g katex`\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "images": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "./docs/source/_static/img/tensor_illustration.png" + }, + "source": "README.md", + "technique": "regular_expression" + }, + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/pytorch/pytorch/master/docs/source/_static/img/dynamic_graph.gif" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "installation": [ + { + "confidence": 1, + "result": { + "original_header": "Binaries", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "Commands to install binaries via Conda or pip wheels are on our website: [https://pytorch.org/get-started/locally/](https://pytorch.org/get-started/locally/)\n\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "NVIDIA Jetson Platforms", + "parent_header": [ + "Installation", + "Binaries" + ], + "type": "Text_excerpt", + "value": "Python wheels for NVIDIA's Jetson Nano, Jetson TX2, and Jetson AGX Xavier are provided [here](https://forums.developer.nvidia.com/t/pytorch-for-jetson-version-1-10-now-available/72048) and the L4T container is published [here](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-pytorch)\n\nThey require JetPack 4.2 and above, and [@dusty-nv](https://github.com/dusty-nv) and [@ptrblck](https://github.com/ptrblck) are maintaining them.\n\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "From Source", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "If you are installing from source, you will need Python 3.7 or later and a C++14 compiler. Also, we highly recommend installing an [Anaconda](https://www.anaconda.com/distribution/#download-section) environment.\nYou will get a high-quality BLAS library (MKL) and you get controlled dependency versions regardless of your Linux distro.\n\nOnce you have [Anaconda](https://www.anaconda.com/distribution/#download-section) installed, here are the instructions.\n\nIf you want to compile with CUDA support, install\n- [NVIDIA CUDA](https://developer.nvidia.com/cuda-downloads) 10.2 or above\n- [NVIDIA cuDNN](https://developer.nvidia.com/cudnn) v7 or above\n- [Compiler](https://gist.github.com/ax3l/9489132) compatible with CUDA\nNote: You could refer to the [cuDNN Support Matrix](https://docs.nvidia.com/deeplearning/cudnn/pdf/cuDNN-Support-Matrix.pdf) for cuDNN versions with the various supported CUDA, CUDA driver and NVIDIA hardwares\n\nIf you want to disable CUDA support, export the environment variable `USE_CUDA=0`.\nOther potentially useful environment variables may be found in `setup.py`.\n\nIf you are building for NVIDIA's Jetson platforms (Jetson Nano, TX1, TX2, AGX Xavier), Instructions to install PyTorch for Jetson Nano are [available here](https://devtalk.nvidia.com/default/topic/1049071/jetson-nano/pytorch-for-jetson-nano/)\n\nIf you want to compile with ROCm support, install\n- [AMD ROCm](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html) 4.0 and above installation\n- ROCm is currently supported only for Linux systems.\n\nIf you want to disable ROCm support, export the environment variable `USE_ROCM=0`.\nOther potentially useful environment variables may be found in `setup.py`.\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Install Dependencies", + "parent_header": [ + "Installation", + "From Source" + ], + "type": "Text_excerpt", + "value": "Common\n```bash\nconda install astunparse numpy ninja pyyaml mkl mkl-include setuptools cmake cffi typing_extensions future six requests dataclasses\n```\n\nOn Linux\n```bash\n# CUDA only: Add LAPACK support for the GPU if needed\nconda install -c pytorch magma-cuda110 # or the magma-cuda* that matches your CUDA version from https://anaconda.org/pytorch/repo\n```\n\nOn MacOS\n```bash\n# Add these packages if torch.distributed is needed\nconda install pkg-config libuv\n```\n\nOn Windows\n```bash\n# Add these packages if torch.distributed is needed.\n# Distributed package support on Windows is a prototype feature and is subject to changes.\nconda install -c conda-forge libuv=1.39\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Install PyTorch", + "parent_header": [ + "Installation", + "From Source" + ], + "type": "Text_excerpt", + "value": "On Linux\n```bash\nexport CMAKE_PREFIX_PATH=${CONDA_PREFIX:-\"$(dirname $(which conda))/../\"}\npython setup.py install\n```\n\nNote that if you are compiling for ROCm, you must run this command first:\n```bash\npython tools/amd_build/build_amd.py\n```\n\nNote that if you are using [Anaconda](https://www.anaconda.com/distribution/#download-section), you may experience an error caused by the linker:\n\n```plaintext\nbuild/temp.linux-x86_64-3.7/torch/csrc/stub.o: file not recognized: file format not recognized\ncollect2: error: ld returned 1 exit status\nerror: command 'g++' failed with exit status 1\n```\n\nThis is caused by `ld` from Conda environment shadowing the system `ld`. You should use a newer version of Python that fixes this issue. The recommended Python version is 3.7.6+ and 3.8.1+.\n\nOn macOS\n```bash\nexport CMAKE_PREFIX_PATH=${CONDA_PREFIX:-\"$(dirname $(which conda))/../\"}\nMACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py install\n```\n\nCUDA is not supported on macOS.\n\n\nOn Windows\n\nChoose Correct Visual Studio Version.\n\nSometimes there are regressions in new versions of Visual Studio, so\nit's best to use the same Visual Studio Version [16.8.5](https://github.com/pytorch/pytorch/blob/master/.circleci/scripts/vs_install.ps1) as Pytorch CI's.\n\nPyTorch CI uses Visual C++ BuildTools, which come with Visual Studio Enterprise,\nProfessional, or Community Editions. You can also install the build tools from\nhttps://visualstudio.microsoft.com/visual-cpp-build-tools/. The build tools *do not*\ncome with Visual Studio Code by default.\n\nIf you want to build legacy python code, please refer to [Building on legacy code and CUDA](https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md#building-on-legacy-code-and-cuda)\n\nBuild with CPU\n\nIt's fairly easy to build with CPU.\n```cmd\nconda activate\npython setup.py install\n```\n\nNote on OpenMP: The desired OpenMP implementation is Intel OpenMP (iomp). In order to link against iomp, you'll need to manually download the library and set up the building environment by tweaking `CMAKE_INCLUDE_PATH` and `LIB`. The instruction [here](https://github.com/pytorch/pytorch/blob/master/docs/source/notes/windows.rst#building-from-source) is an example for setting up both MKL and Intel OpenMP. Without these configurations for CMake, Microsoft Visual C OpenMP runtime (vcomp) will be used.\n\nBuild with CUDA\n\n[NVTX](https://docs.nvidia.com/gameworks/content/gameworkslibrary/nvtx/nvidia_tools_extension_library_nvtx.htm) is needed to build Pytorch with CUDA.\nNVTX is a part of CUDA distributive, where it is called \"Nsight Compute\". To install it onto already installed CUDA run CUDA installation once again and check the corresponding checkbox.\nMake sure that CUDA with Nsight Compute is installed after Visual Studio.\n\nCurrently, VS 2017 / 2019, and Ninja are supported as the generator of CMake. If `ninja.exe` is detected in `PATH`, then Ninja will be used as the default generator, otherwise, it will use VS 2017 / 2019.\n
If Ninja is selected as the generator, the latest MSVC will get selected as the underlying toolchain.\n\nAdditional libraries such as\n[Magma](https://developer.nvidia.com/magma), [oneDNN, a.k.a MKLDNN or DNNL](https://github.com/oneapi-src/oneDNN), and [Sccache](https://github.com/mozilla/sccache) are often needed. Please refer to the [installation-helper](https://github.com/pytorch/pytorch/tree/master/.jenkins/pytorch/win-test-helpers/installation-helpers) to install them.\n\nYou can refer to the [build_pytorch.bat](https://github.com/pytorch/pytorch/blob/master/.jenkins/pytorch/win-test-helpers/build_pytorch.bat) script for some other environment variables configurations\n\n\n```cmd\ncmd\n\n:: Set the environment variables after you have downloaded and upzipped the mkl package,\n:: else CMake would throw an error as `Could NOT find OpenMP`.\nset CMAKE_INCLUDE_PATH={Your directory}\\mkl\\include\nset LIB={Your directory}\\mkl\\lib;%LIB%\n\n:: Read the content in the previous section carefully before you proceed.\n:: [Optional] If you want to override the underlying toolset used by Ninja and Visual Studio with CUDA, please run the following script block.\n:: \"Visual Studio 2019 Developer Command Prompt\" will be run automatically.\n:: Make sure you have CMake >= 3.12 before you do this when you use the Visual Studio generator.\nset CMAKE_GENERATOR_TOOLSET_VERSION=14.27\nset DISTUTILS_USE_SDK=1\nfor /f \"usebackq tokens=*\" %i in (`\"%ProgramFiles(x86)%\\Microsoft Visual Studio\\Installer\\vswhere.exe\" -version [15^,17^) -products * -latest -property installationPath`) do call \"%i\\VC\\Auxiliary\\Build\\vcvarsall.bat\" x64 -vcvars_ver=%CMAKE_GENERATOR_TOOLSET_VERSION%\n\n:: [Optional] If you want to override the CUDA host compiler\nset CUDAHOSTCXX=C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.27.29110\\bin\\HostX64\\x64\\cl.exe\n\npython setup.py install\n\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Adjust Build Options (Optional)", + "parent_header": [ + "Installation", + "From Source", + "Install PyTorch" + ], + "type": "Text_excerpt", + "value": "You can adjust the configuration of cmake variables optionally (without building first), by doing\nthe following. For example, adjusting the pre-detected directories for CuDNN or BLAS can be done\nwith such a step.\n\nOn Linux\n```bash\nexport CMAKE_PREFIX_PATH=${CONDA_PREFIX:-\"$(dirname $(which conda))/../\"}\npython setup.py build --cmake-only\nccmake build # or cmake-gui build\n```\n\nOn macOS\n```bash\nexport CMAKE_PREFIX_PATH=${CONDA_PREFIX:-\"$(dirname $(which conda))/../\"}\nMACOSX_DEPLOYMENT_TARGET=10.9 CC=clang CXX=clang++ python setup.py build --cmake-only\nccmake build # or cmake-gui build\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Using pre-built images", + "parent_header": [ + "Installation", + "Docker Image" + ], + "type": "Text_excerpt", + "value": "You can also pull a pre-built docker image from Docker Hub and run with docker v19.03+\n\n```bash\ndocker run --gpus all --rm -ti --ipc=host pytorch/pytorch:latest\n```\n\nPlease note that PyTorch uses shared memory to share data between processes, so if torch multiprocessing is used (e.g.\nfor multithreaded data loaders) the default shared memory segment size that container runs with is not enough, and you\nshould increase shared memory size either with `--ipc=host` or `--shm-size` command line options to `nvidia-docker run`.\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Building the image yourself", + "parent_header": [ + "Installation", + "Docker Image" + ], + "type": "Text_excerpt", + "value": "**NOTE:** Must be built with a docker version > 18.06\n\nThe `Dockerfile` is supplied to build images with CUDA 11.1 support and cuDNN v8.\nYou can pass `PYTHON_VERSION=x.y` make variable to specify which Python version is to be used by Miniconda, or leave it\nunset to use the default.\n```bash\nmake -f docker.Makefile\n# images are tagged as docker.io/${your_docker_username}/pytorch\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Previous Versions", + "parent_header": [ + "Installation" + ], + "type": "Text_excerpt", + "value": "Installation instructions and binaries for previous PyTorch versions may be found\non [our website](https://pytorch.org/previous-versions).\n\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "license": [ + { + "confidence": 1, + "result": { + "original_header": "License", + "type": "Text_excerpt", + "value": "PyTorch has a BSD-style license, as found in the [LICENSE](LICENSE) file.\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "logo": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/pytorch/pytorch/master/docs/source/_static/img/pytorch-logo-dark.png" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "package_distribution": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://anaconda.org/pytorch/repo" + }, + "source": "README.md", + "technique": "regular_expression" + } + ], + "requirements": [ + { + "confidence": 1, + "result": { + "original_header": "Install Dependencies", + "parent_header": [ + "Installation", + "From Source" + ], + "type": "Text_excerpt", + "value": "Common\n```bash\nconda install astunparse numpy ninja pyyaml mkl mkl-include setuptools cmake cffi typing_extensions future six requests dataclasses\n```\n\nOn Linux\n```bash\n# CUDA only: Add LAPACK support for the GPU if needed\nconda install -c pytorch magma-cuda110 # or the magma-cuda* that matches your CUDA version from https://anaconda.org/pytorch/repo\n```\n\nOn MacOS\n```bash\n# Add these packages if torch.distributed is needed\nconda install pkg-config libuv\n```\n\nOn Windows\n```bash\n# Add these packages if torch.distributed is needed.\n# Distributed package support on Windows is a prototype feature and is subject to changes.\nconda install -c conda-forge libuv=1.39\n```\n" + }, + "source": null, + "technique": "header_analysis" + } + ], + "somef_missing_categories": [ + "application_domain", + "acknowledgement", + "authors", + "citation", + "contributors", + "continuous_integration", + "code_of_conduct", + "code_repository", + "contact", + "description", + "date_created", + "date_updated", + "download", + "download_url", + "executable_example", + "faq", + "forks_count", + "forks_url", + "full_name", + "full_title", + "has_build_file", + "has_script_file", + "identifier", + "invocation", + "issue_tracker", + "homepage", + "keywords", + "name", + "ontologies", + "owner", + "has_package_file", + "programming_languages", + "readme_url", + "related_documentation", + "releases", + "run", + "runtime_platform", + "related_papers", + "repository_status", + "stargazers_count", + "support", + "support_channels", + "workflows", + "type" + ], + "somef_provenance": { + "date": "2026-01-20 09:38:35", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Get the PyTorch Source", + "parent_header": [ + "Installation", + "From Source" + ], + "type": "Text_excerpt", + "value": "```bash\ngit clone --recursive https://github.com/pytorch/pytorch\ncd pytorch\n# if you are updating an existing checkout\ngit submodule sync\ngit submodule update --init --recursive --jobs 0\n```\n" + }, + "source": null, + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Getting Started", + "type": "Text_excerpt", + "value": "Three-pointers to get you started:\n- [Tutorials: get you started with understanding and using PyTorch](https://pytorch.org/tutorials/)\n- [Examples: easy to understand PyTorch code across all domains](https://github.com/pytorch/examples)\n- [The API Reference](https://pytorch.org/docs/)\n- [Glossary](https://github.com/pytorch/pytorch/blob/master/GLOSSARY.md)\n" + }, + "source": null, + "technique": "header_analysis" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test-ecfo.json b/src/somef_core/test/test_data/test-ecfo.json new file mode 100644 index 0000000..639f0f5 --- /dev/null +++ b/src/somef_core/test/test_data/test-ecfo.json @@ -0,0 +1,414 @@ +{ + "citation": [ + { + "confidence": 1, + "result": { + "author": [ + { + "family_name": "Markovic", + "given_name": "Milan", + "name": "Milan Markovic", + "type": "Agent", + "url": "https://orcid.org/0000-0002-5477-287X" + }, + { + "family_name": "Garijo", + "given_name": "Daniel", + "name": "Daniel Garijo", + "type": "Agent", + "url": "https://orcid.org/0000-0003-0454-7145" + }, + { + "family_name": "Germano", + "given_name": "Stefano", + "name": "Stefano Germano", + "type": "Agent", + "url": "https://orcid.org/0000-0001-6993-0618" + }, + { + "family_name": "Naja", + "given_name": "Iman", + "name": "Iman Naja", + "type": "Agent", + "url": "https://orcid.org/0000-0001-6634-3266" + } + ], + "datePublished": "2023", + "doi": "10.5281/zenodo.7916079", + "format": "cff", + "title": "ECFO - Emission Conversion Factors Ontology", + "type": "File_dump", + "url": "https://doi.org/10.5281/zenodo.7916079", + "value": "cff-version: 1.2.0\ntitle: ECFO - Emission Conversion Factors Ontology\nmessage: 'If you use this resource, please cite it as below.'\ntype: software\nauthors:\n - family-names: Markovic\n given-names: Milan\n orcid: 'https://orcid.org/0000-0002-5477-287X'\n - family-names: Garijo\n given-names: Daniel\n orcid: 'https://orcid.org/0000-0003-0454-7145'\n - family-names: Germano\n given-names: Stefano\n orcid: 'https://orcid.org/0000-0001-6993-0618'\n - family-names: Naja\n given-names: Iman\n orcid: 'https://orcid.org/0000-0001-6634-3266'\nurl: 'https://w3id.org/ecfo'\nversion: 1.0.0\ndate-released: '2023-05-09'\ndoi: 10.5281/zenodo.7916079\npreferred-citation:\n authors:\n - family-names: Markovic\n given-names: Milan\n orcid: 'https://orcid.org/0000-0002-5477-287X'\n - family-names: Garijo\n given-names: Daniel\n orcid: 'https://orcid.org/0000-0003-0454-7145'\n - family-names: Germano\n given-names: Stefano\n orcid: 'https://orcid.org/0000-0001-6993-0618'\n - family-names: Naja\n given-names: Iman\n orcid: 'https://orcid.org/0000-0001-6634-3266'\n title: \"TEC: Transparent Emissions Calculation Toolkit\"\n type: article\n year: 2023\n doi: 10.1007/978-3-031-47243-5_5\n" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/CITATION.cff", + "technique": "file_exploration" + } + ], + "code_repository": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/TEC-Toolkit/ECFO" + }, + "technique": "GitHub_API" + } + ], + "contributing_guidelines": [ + { + "confidence": 1, + "result": { + "type": "File_dump", + "value": "# How to contribute\n\nThank you for investing your time in contributing to the ECFO ontology!\n\nTo get an overview of the project, please read the [README](README.md).\n\n### Issues\n\n#### Create a new issue\n\nIf you spot a problem or want to suggest a new term or use case, [search if it already exists in our issue tracker](https://github.com/TEC-Toolkit/ECFO/issues).\nIf a related issue does not exist, you can open a new issue here on GitHub.\n\n### Proposing new changes to the ontology\n1. Edit the ontology using your favorite program. The latest version of the ontology can be found in the `development` folder.\n2. Don't forget to add the motivation of your change, as well as metadata for the terms you would like to include\n\n#### Make changes locally\n\n1. Fork the repository.\n - Using GitHub Desktop:\n - [Getting started with GitHub Desktop](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop) will guide you through setting up Desktop.\n - Once Desktop is set up, you can use it to [fork the repo](https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop)!\n - Using the command line:\n - [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo#fork-an-example-repository) so that you can make your changes without affecting the original project until you're ready to merge them.\n2. Create a working branch and start with your changes!\n\n### Commit your update\n\nCommit the changes once you are happy with them.\n\nAlways write a clear log message for your commits.\nOne-line messages are fine for small changes.\n\n### Pull Request\n\nWhen you're finished with the changes, create a pull request, also known as a PR.\n\n- Link your PR to the issue it addresses.\n- Push your PR to the `dev` branch. One of the members of the team will merge it in the main branch.\n\n" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/CONTRIBUTING.md", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "original_header": "Contributing", + "type": "Text_excerpt", + "value": "Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the process for submitting pull requests to us. Remember that the last version of the ontology can be found in the `development` folder\n\n---\n\n
\n\n This ontology is part of the [TEC-Toolkit](https://github.com/TEC-Toolkit).\n\n \"TEC-Toolkit\n\n
" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md", + "technique": "header_analysis" + } + ], + "date_created": [ + { + "confidence": 1, + "result": { + "type": "Date", + "value": "2022-11-15T14:30:47Z" + }, + "technique": "GitHub_API" + } + ], + "date_updated": [ + { + "confidence": 1, + "result": { + "type": "Date", + "value": "2025-10-06T13:04:14Z" + }, + "technique": "GitHub_API" + } + ], + "description": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "The Emission Conversion Factor Ontology" + }, + "technique": "GitHub_API" + } + ], + "download_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/Tec-Toolkit/ECFO/releases" + }, + "technique": "GitHub_API" + } + ], + "forks_count": [ + { + "confidence": 1, + "result": { + "type": "Number", + "value": 1 + }, + "technique": "GitHub_API" + } + ], + "forks_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://api.github.com/repos/TEC-Toolkit/ECFO/forks" + }, + "technique": "GitHub_API" + } + ], + "full_name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "TEC-Toolkit/ECFO" + }, + "technique": "GitHub_API" + } + ], + "homepage": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://w3id.org/ecfo" + }, + "technique": "GitHub_API" + } + ], + "identifier": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://zenodo.org/badge/latestdoi/566369718" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md", + "technique": "regular_expression" + } + ], + "issue_tracker": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://api.github.com/repos/TEC-Toolkit/ECFO/issues" + }, + "technique": "GitHub_API" + } + ], + "keywords": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "climate-change, conversion-factor, emission-conversion-factor, ontology" + }, + "technique": "GitHub_API" + } + ], + "license": [ + { + "confidence": 1, + "result": { + "type": "File_dump", + "value": "This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.\n" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/LICENSE.md", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "original_header": "License", + "type": "Text_excerpt", + "value": "This project is licensed under the Creative Commons Attribution 4.0 International License - see the [LICENSE.md](LICENSE.md) file for details.\n\n\n" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md", + "technique": "header_analysis" + } + ], + "logo": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://tec-toolkit.github.io/assets/Logo%20TEC.svg" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md", + "technique": "regular_expression" + } + ], + "name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "ECFO" + }, + "technique": "GitHub_API" + } + ], + "owner": [ + { + "confidence": 1, + "result": { + "type": "Organization", + "value": "TEC-Toolkit" + }, + "technique": "GitHub_API" + } + ], + "programming_languages": [ + { + "confidence": 1, + "result": { + "name": "JavaScript", + "size": 3303615, + "type": "Programming_language", + "value": "JavaScript" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "name": "HTML", + "size": 277847, + "type": "Programming_language", + "value": "HTML" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "name": "CSS", + "size": 176942, + "type": "Programming_language", + "value": "CSS" + }, + "technique": "GitHub_API" + } + ], + "readme_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md" + }, + "technique": "file_exploration" + } + ], + "releases": [ + { + "confidence": 1, + "result": { + "assets": [], + "author": { + "name": "dgarijo", + "type": "User" + }, + "date_created": "2023-05-09T16:14:42Z", + "date_published": "2023-05-09T16:53:17Z", + "description": "This release fixed minor issues in the annotations, and adds full metadata about the ontology.", + "html_url": "https://github.com/TEC-Toolkit/ECFO/releases/tag/1.0.0", + "name": "ECFO 1.0.0: Release with metadata and documentation", + "release_id": 102378234, + "tag": "1.0.0", + "tarball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/tarball/1.0.0", + "type": "Release", + "url": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/102378234", + "value": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/102378234", + "zipball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/zipball/1.0.0" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "assets": [], + "author": { + "name": "dgarijo", + "type": "User" + }, + "date_created": "2023-04-20T14:55:40Z", + "date_published": "2023-04-20T14:57:56Z", + "description": "This new release completes the CQs, homogeneizes properties and defines new ones to specify what a CF is converting and what it is converting to (e.g., Butane -> CO2)", + "html_url": "https://github.com/TEC-Toolkit/ECFO/releases/tag/0.0.2", + "name": "ECFO 0.0.2: New properties for emission source and target ", + "release_id": 100216030, + "tag": "0.0.2", + "tarball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/tarball/0.0.2", + "type": "Release", + "url": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/100216030", + "value": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/100216030", + "zipball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/zipball/0.0.2" + }, + "technique": "GitHub_API" + }, + { + "confidence": 1, + "result": { + "assets": [], + "author": { + "name": "dgarijo", + "type": "User" + }, + "date_created": "2023-04-05T20:17:42Z", + "date_published": "2023-04-20T10:12:19Z", + "description": "Release of the first version of ECFO, published at https://w3id.org/ecfo/0.0.1", + "html_url": "https://github.com/TEC-Toolkit/ECFO/releases/tag/0.0.1", + "name": "First version of ECFO", + "release_id": 100176341, + "tag": "0.0.1", + "tarball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/tarball/0.0.1", + "type": "Release", + "url": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/100176341", + "value": "https://api.github.com/repos/TEC-Toolkit/ECFO/releases/100176341", + "zipball_url": "https://api.github.com/repos/TEC-Toolkit/ECFO/zipball/0.0.1" + }, + "technique": "GitHub_API" + } + ], + "somef_missing_categories": [ + "application_domain", + "acknowledgement", + "authors", + "contributors", + "continuous_integration", + "code_of_conduct", + "contact", + "documentation", + "download", + "executable_example", + "faq", + "full_title", + "has_build_file", + "has_script_file", + "images", + "installation", + "invocation", + "ontologies", + "package_distribution", + "has_package_file", + "related_documentation", + "run", + "runtime_platform", + "related_papers", + "repository_status", + "requirements", + "support", + "support_channels", + "workflows", + "type" + ], + "somef_provenance": { + "date": "2026-01-20 09:46:13", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.13" + }, + "stargazers_count": [ + { + "confidence": 1, + "result": { + "type": "Number", + "value": 1 + }, + "technique": "GitHub_API" + } + ], + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Getting Started", + "type": "Text_excerpt", + "value": "This ontology is available at [https://w3id.org/ecfo#](https://w3id.org/ecfo#) with content negotiation in RDF/XML, TTL, JSON-LD and N-Triples.\n\nTo download the ontology in different serializations, you can use a curl command like:\n\n```sh\ncurl -sH \"Accept:text/turtle\" -L https://w3id.org/ecfo#\n```\n\nTo see the documentation of the ontology, just open its URI on a browser.\n\n\n" + }, + "source": "https://raw.githubusercontent.com/Tec-Toolkit/ECFO/main/README.md", + "technique": "header_analysis" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_data/test_extract_dois.txt b/src/somef_core/test/test_data/test_extract_dois.txt index fe3da48..2548334 100644 --- a/src/somef_core/test/test_data/test_extract_dois.txt +++ b/src/somef_core/test/test_data/test_extract_dois.txt @@ -2,4 +2,7 @@ Title goes here (with another undesired link) [![DOI](https://zenodo.org/badge/11427075.svg)](https://zenodo.org/badge/latestdoi/11427075)[![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) Some text. Another DOI below: [![DOI](https://zenodo.org/badge/11427077.svg)](https://zenodo.org/badge/latestdoi/11427077) + Another DOI: + [![DOI](https://zenodo.org/badge/11427075.svg)](https://zenodo.org/badge/DOI/11427075)[![](https://jitpack.io/v/dgarijo/Widoco.svg)](https://jitpack.io/#dgarijo/Widoco) + diff --git a/src/somef_core/test/test_data/test_widoco_runtime_platform.json b/src/somef_core/test/test_data/test_widoco_runtime_platform.json new file mode 100644 index 0000000..ef9f0bd --- /dev/null +++ b/src/somef_core/test/test_data/test_widoco_runtime_platform.json @@ -0,0 +1,570 @@ +{ + "application_domain": [ + { + "confidence": 0.9698829880598062, + "result": { + "type": "String", + "value": "Semantic web" + }, + "technique": "supervised_classification" + } + ], + "citation": [ + { + "confidence": 1, + "result": { + "author": [ + { + "family_name": "Garijo", + "given_name": "Daniel", + "name": "Daniel Garijo", + "type": "Agent", + "url": "http://orcid.org/0000-0003-0454-7145" + } + ], + "datePublished": "2017", + "doi": "10.1007/978-3-319-68204-4_9", + "format": "cff", + "title": "WIDOCO: A Wizard for documenting ontologies", + "type": "File_dump", + "url": "https://doi.org/10.5281/zenodo.591294", + "value": "title: \"WIDOCO: A Wizard for documenting ontologies\"\nlicense: Apache-2.0\nauthors:\n - family-names: Garijo\n given-names: Daniel\n orcid: \"http://orcid.org/0000-0003-0454-7145\"\ncff-version: 1.2.0\nmessage: \"If you use this software, please cite both the article from preferred-citation and the software itself.\"\npreferred-citation:\n authors:\n - family-names: Garijo\n given-names: Daniel\n title: \"WIDOCO: A wizard for documenting ontologies\"\n type: article\n year: 2017\n doi: 10.1007/978-3-319-68204-4_9\nidentifiers:\n - description: \"Collection of archived snapshots for WIDOCO\"\n type: doi\n value: 10.5281/zenodo.591294\n" + }, + "source": "https://raw.githubusercontent.com/True///CITATION.cff", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "author": "Garijo, Daniel", + "doi": "10.1007/978-3-319-68204-4_9", + "format": "bibtex", + "title": "WIDOCO: a wizard for documenting ontologies", + "type": "Text_excerpt", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "value": "@inproceedings{garijo2017widoco,\n url = {http://dgarijo.com/papers/widoco-iswc2017.pdf},\n funding = {USNSF ICER-1541029, NIH 1R01GM117097-01},\n doi = {10.1007/978-3-319-68204-4_9},\n organization = {Springer, Cham},\n year = {2017},\n pages = {94--102},\n booktitle = {International Semantic Web Conference},\n author = {Garijo, Daniel},\n title = {WIDOCO: a wizard for documenting ontologies},\n}" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "code_repository": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "contributing_guidelines": [ + { + "confidence": 1, + "result": { + "type": "File_dump", + "value": "## Contribution guidelines\nContributions to address any of the current issues are welcome. In order to push your contribution, just **push your pull request to the develop branch**. The master branch has only the code associated to the latest release. \n" + }, + "source": "https://raw.githubusercontent.com/True///CONTRIBUTING.md", + "technique": "file_exploration" + } + ], + "date_created": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "2013-07-15" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "date_updated": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "2025-01-31" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "description": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": [ + "Wizard for documenting ontologies. WIDOCO is a step by step generator of HTML templates with the documentation of your ontology. It uses the LODE environment to create part of the template.", + "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now **you can use Markdown on your class descriptions** (see [example](https://dgarijo.github.io/Widoco/doc/gallery/index.html))\n* Massive metadata extraction and support: WIDOCO will enhance your ontology documentation based on your ontology annotations. Now you can add custom logos and images, edit the content of your sections, etc. by just editing metadata. See our [supported metadata](doc/metadataGuide/guide.md) and [recommendations](https://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) for more information.\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](https://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + ] + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "original_header": "Description", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology, by following a series of steps in a wizard. We extend the LODE framework by Silvio Peroni to describe the classes, properties and data properties of the ontology, the OOPS! webservice by Mar\u00eda Poveda to print an evaluation and the Licensius service by Victor Rodriguez Doncel to determine the license URI and title being used. In addition, we use WebVowl to visualize the ontology and have extended Bubastis to show a complete changelog between different versions of your ontology.\n\nFeatures of WIDOCO:\n* Automatic documentation of the terms in your ontology (based on [LODE](http://www.essepuntato.it/lode/)). Now you can use Markdown on your class descriptions (see [example](doc/gallery/index.html))\n* Automatic annotation in JSON-LD snippets of the html produced.\n* Association of a provenance page which includes the history of your vocabulary (W3C PROV-O compliant).\n* Metadata extraction from the ontology plus the means to complete it on the fly when generating your ontology. Check the [best practice document](http://dgarijo.github.io/Widoco/doc/bestPractices/index-en.html) to know more about the terms recognized by WIDOCO.\n* Guidelines on the main sections that your document should have and how to complete them.\n* Integration with diagram creators ([WebVOWL](http://vowl.visualdataweb.org/webvowl/)).\n* Automatic changelog of differences between the actual and the previous version of the ontology (based on [Bubastis](http://www.ebi.ac.uk/efo/bubastis/)).\n* Separation of the sections of your html page so you can write them independently and replace only those needed.\n* Content negotiation and serialization of your ontology according to [W3C best practices](https://www.w3.org/TR/swbp-vocab-pub/)\n* Evaluation reports of your ontology (using the [OOPS! web service](http://oops.linkeddata.es/))\n* Integration with license metadata services ([Licensius](http://licensius.com/)) to automatically describe the license used in your ontology.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 0.9336412604289143, + "result": { + "original_header": "WIzard for DOCumenting Ontologies (WIDOCO)", + "type": "Text_excerpt", + "value": "WIDOCO helps you to publish and create an enriched and customized documentation of your ontology automatically, by following a series of steps in a GUI. \n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "supervised_classification" + }, + { + "confidence": 0.9682942149713352, + "result": { + "original_header": "Current improvements", + "type": "Text_excerpt", + "value": "For a complete list of the current improvements and next features, check the [project open issues](https://github.com/dgarijo/Widoco/issues) and [milestones](https://github.com/dgarijo/Widoco/milestones) in the repository.\n \n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "supervised_classification" + } + ], + "documentation": [ + { + "confidence": 1, + "result": { + "original_header": "Browser issues (Why can't I see the generated documentation / visualization?)", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "WIDOCO separates the contents of different sections in HTML files, which are then loaded in the `index.html` file. WIDOCO was designed this way because it's easier to edit your introduction or description sections independently without being all aggregated together in a huge HTML document. **When all the contents generated by WIDOCO are stored in a server, you will be able to see the documentation of your ontology using any browser**. However, if you open the `index.html` file **on your local browser**, you may see a document missing most of the sections in your documentation. This happens because browsers don't allow loading separate content when opening a file locally for security reasons. If you want to explore how your ontology would look locally, you have two options:\n\n* a) Execute WIDOCO with the `-uniteSections` flag; or select the option `add al sections in a single document` in the \"load sections\" step in the WIDOCO GUI. This will make all the sections of WIDOCO to be in the `index.html`; and you will be able to see it in your browser. Note that the **LODE visualization will not be available** when exploring your ontology locally.\n* b) Create a local server: Set up a local server (e.g., using XAMPP or Tomcat) and serve the files WIDOCO generates (in the `htdocs` folder for Apache servers).\n\nIf you place the files generated by WIDOCO in a server and access them via its URL (for example, a Github page), you should be able to see your documentation appropriately.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "download": [ + { + "confidence": 1, + "result": { + "original_header": "Downloading the executable", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "To download WIDOCO, you need to download a JAR executable file. Check the latest release for more details: (https://github.com/dgarijo/WIDOCO/releases/latest).\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "download_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco/releases" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "full_title": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "WIzard for DOCumenting Ontologies (WIDOCO)" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "has_build_file": [ + { + "confidence": 1, + "result": { + "format": "dockerfile", + "type": "Url", + "value": "https://raw.githubusercontent.com/True///Dockerfile" + }, + "source": "https://raw.githubusercontent.com/True///Dockerfile", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "format": "pom.xml", + "type": "Url", + "value": "https://raw.githubusercontent.com/True///pom.xml" + }, + "source": "https://raw.githubusercontent.com/True///pom.xml", + "technique": "file_exploration" + } + ], + "identifier": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "https://doi.org/10.5281/zenodo.11093793" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://zenodo.org/badge/latestdoi/11427075" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "issue_tracker": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://github.com/dgarijo/Widoco/issues" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "keywords": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": [ + "documentation", + "metadata", + "ontology", + "ontology-diagram", + "ontology-evaluation", + "wizard" + ] + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "license": [ + { + "confidence": 1, + "result": { + "name": "Apache License 2.0", + "spdx_id": "Apache-2.0", + "type": "File_dump", + "value": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under this License for that Work shall terminate\n as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n Work or Derivative Works thereof in any medium, with or without\n modifications, and in Source or Object form, provided that You\n meet the following conditions:\n\n (a) You must give any other recipients of the Work or\n Derivative Works a copy of this License; and\n\n (b) You must cause any modified files to carry prominent notices\n stating that You changed the files; and\n\n (c) You must retain, in the Source form of any Derivative Works\n that You distribute, all copyright, patent, trademark, and\n attribution notices from the Source form of the Work,\n excluding those notices that do not pertain to any part of\n the Derivative Works; and\n\n (d) If the Work includes a \"NOTICE\" text file as part of its\n distribution, then any Derivative Works that You distribute must\n include a readable copy of the attribution notices contained\n within such NOTICE file, excluding those notices that do not\n pertain to any part of the Derivative Works, in at least one\n of the following places: within a NOTICE text file distributed\n as part of the Derivative Works; within the Source form or\n documentation, if provided along with the Derivative Works; or,\n within a display generated by the Derivative Works, if and\n wherever such third-party notices normally appear. The contents\n of the NOTICE file are for informational purposes only and\n do not modify the License. You may add Your own attribution\n notices within Derivative Works that You distribute, alongside\n or as an addendum to the NOTICE text from the Work, provided\n that such additional attribution notices cannot be construed\n as modifying the License.\n\n You may add Your own copyright statement to Your modifications and\n may provide additional or different license terms and conditions\n for use, reproduction, or distribution of Your modifications, or\n for any such Derivative Works as a whole, provided Your use,\n reproduction, and distribution of the Work otherwise complies with\n the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n any Contribution intentionally submitted for inclusion in the Work\n by You to the Licensor shall be under the terms and conditions of\n this License, without any additional terms or conditions.\n Notwithstanding the above, nothing herein shall supersede or modify\n the terms of any separate license agreement you may have executed\n with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n names, trademarks, service marks, or product names of the Licensor,\n except as required for reasonable and customary use in describing the\n origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n agreed to in writing, Licensor provides the Work (and each\n Contributor provides its Contributions) on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n implied, including, without limitation, any warranties or conditions\n of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n PARTICULAR PURPOSE. You are solely responsible for determining the\n appropriateness of using or redistributing the Work and assume any\n risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n whether in tort (including negligence), contract, or otherwise,\n unless required by applicable law (such as deliberate and grossly\n negligent acts) or agreed to in writing, shall any Contributor be\n liable to You for damages, including any direct, indirect, special,\n incidental, or consequential damages of any character arising as a\n result of this License or out of the use or inability to use the\n Work (including but not limited to damages for loss of goodwill,\n work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses), even if such Contributor\n has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n the Work or Derivative Works thereof, You may choose to offer,\n and charge a fee for, acceptance of support, warranty, indemnity,\n or other liability obligations and/or rights consistent with this\n License. However, in accepting such obligations, You may act only\n on Your own behalf and on Your sole responsibility, not on behalf\n of any other Contributor, and only if You agree to indemnify,\n defend, and hold each Contributor harmless for any liability\n incurred by, or claims asserted against, such Contributor by reason\n of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"{}\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n\n Copyright {2016} {Daniel Garijo, Information Sciences Institute, USC.}\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n" + }, + "source": "https://raw.githubusercontent.com/True///LICENSE", + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "identifier": "https://spdx.org/licenses/Apache-2.0", + "spdx_id": "Apache-2.0", + "type": "License", + "url": "https://raw.githubusercontent.com/dgarijo/Widoco/master/LICENSE", + "value": "Apache License 2.0" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "logo": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "/Users/mbp_jjm/Documents/DOCUMENTACION UPM/somef/src/somef/test/test_data/repositories/Widoco/src/main/resources/logo/logo2.png" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "name": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "Widoco" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "ontologies": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/True///example_onto/ontology.nt" + }, + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/True///example_onto/ontology.ttl" + }, + "technique": "file_exploration" + } + ], + "programming_languages": [ + { + "confidence": 1, + "result": { + "name": "JavaScript", + "type": "Programming_language", + "value": "JavaScript" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "Java", + "type": "Programming_language", + "value": "Java" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "XSLT", + "type": "Programming_language", + "value": "XSLT" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "CSS", + "type": "Programming_language", + "value": "CSS" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "HTML", + "type": "Programming_language", + "value": "HTML" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "name": "Dockerfile", + "type": "Programming_language", + "value": "Dockerfile" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "readme_url": [ + { + "confidence": 1, + "result": { + "type": "Url", + "value": "https://raw.githubusercontent.com/True///README.md" + }, + "technique": "file_exploration" + }, + { + "confidence": 1, + "result": { + "type": "String", + "value": "https://raw.githubusercontent.com/dgarijo/Widoco/master/README.md" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "reference_publication": [ + { + "confidence": 1, + "result": { + "date_published": "2017", + "doi": "10.1007/978-3-319-68204-4_9", + "title": "WIDOCO: a wizard for documenting ontologies", + "type": "Scholarly_article", + "url": "http://dgarijo.com/papers/widoco-iswc2017.pdf", + "value": "WIDOCO: a wizard for documenting ontologies" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ], + "repository_status": [ + { + "confidence": 1, + "result": { + "description": "Active \u2013 The project has reached a stable, usable state and is being actively developed.", + "type": "Url", + "value": "https://www.repostatus.org/#active" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "regular_expression" + } + ], + "requirements": [ + { + "confidence": 1, + "result": { + "type": "Software_application", + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.24\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "type": "Software_application", + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file." + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + }, + { + "confidence": 1, + "result": { + "original_header": "Importing WIDOCO as a dependency", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "Just add the dependency and repository to your `pom.xml` file as follows. See the [WIDOCO JitPack](https://jitpack.io/#dgarijo/Widoco) page to find alternative means to incorporate WIDOCO to your project.\n\n```xml\n\n \n com.github.dgarijo\n Widoco\n v1.4.16\n \n\n\n[ ... ]\n\n\n\t\n\t jitpack.io\n\t https://jitpack.io\n\t\n\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Requirements", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "You will need Java 1.8 or higher (SDK 1.8 or JRE 8) for WIDOCO to work\nOtherwise, you will probably experience an \"Unsupported major.minor version 52.0\" exception when executing the JAR file.\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "somef_provenance": { + "date": "2025-10-13 12:13:01", + "somef_schema_version": "1.0.0", + "somef_version": "0.9.12" + }, + "usage": [ + { + "confidence": 1, + "result": { + "original_header": "Examples", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "Examples of the features of WIDOCO can be seen on [the gallery](http://dgarijo.github.io/Widoco/doc/gallery/)\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "GUI Tutorial", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)" + ], + "type": "Text_excerpt", + "value": "A tutorial explaining the main features of the GUI can be found [here](http://dgarijo.github.io/Widoco/doc/tutorial/) \n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "JAR execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "Download the latest `.jar` [WIDOCO available release](https://github.com/dgarijo/WIDOCO/releases/latest) (it will be something like `widoco-VERSION-jar-with-dependencies.jar`). Then just double click the `.jar` file.\n\nYou may also execute WIDOCO through the command line. Usage:\n```bash\njava -jar widoco-VERSION-jar-with-dependencies.jar [OPTIONS]\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Docker execution", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "First build the image using the `Dockerfile` in project folder:\n\n```bash\ndocker build -t dgarijo/widoco .\n```\n\nYou can now execute WIDOCO through the command line. Usage:\n\n```bash\ndocker run -ti --rm dgarijo/widoco [OPTIONS]\n```\n\nIf you want to share data between the Docker Container and your Host, for instance to load a local ontology file (from PATH), you will need to mount the container\nwith host directories. For instance:\n\n```bash\ndocker run -ti --rm \\\n -v `pwd`/test:/usr/local/widoco/in \\\n -v `pwd`/target/generated-doc:/usr/local/widoco/out \\\n dgarijo/widoco -ontFile in/bne.ttl -outFolder out -rewriteAll\n```\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + }, + { + "confidence": 1, + "result": { + "original_header": "Options", + "parent_header": [ + "WIzard for DOCumenting Ontologies (WIDOCO)", + "How to use WIDOCO" + ], + "type": "Text_excerpt", + "value": "`-ontFile PATH` [required (unless -ontURI is used)]: Load a local ontology file (from PATH) to document. This option is incompatible with -ontURI\n\n`-ontURI URI` [required (unless -ontFile is used)]: Load an ontology to document from its URI. This option is incompatible with -ontFile\n\n`-outFolder folderName`: Specifies the name of the folder where to save the documentation. By default is 'myDocumentation'\n\n`-confFile PATH`: Load your own configuration file for the ontology metadata. Incompatible with -getOntologyMetadata\n\n`-getOntologyMetadata`: Extract ontology metadata from the given ontology\n\n`-oops`: Create an html page with the evaluation from the OOPS service (http://oops.linkeddata.es/)\n\n`-rewriteAll`: Replace any existing files when documenting an ontology (e.g., from a previous execution)\n\n`-crossRef`: ONLY generate the overview and cross reference sections. The index document will NOT be generated. The htaccess, provenance page, etc., will not be generated unless requested by other flags. This flag is intended to be used only after a first version of the documentation exists.\n\n`-saveConfig PATH`: Save a configuration file on PATH with the properties of a given ontology\n\n`-useCustomStyle`: Export the documentation using alternate css files (by Daniel Vila).\n\n`-lang LANG1-LANG2`: Generate documentation in multiple languages (separated by \"-\"). Note that if the language is not supported, the system will load the labels in english. For example: en-pt-es\n\n`-includeImportedOntologies`: Indicates whether the terms of the imported ontologies of the current ontology should be documented as well or not.\n\n`-htaccess`: Create a bundle for publication ready to be deployed on your Apache server.\n\n`-webVowl`: Create a visualization based on WebVowl (http://vowl.visualdataweb.org/webvowl/index.html#) in the documentation.\n\n`-licensius`: Use the Licensius web services (http://licensius.com/apidoc/index.html) to retrieve license metadata. Only works if the -getOntologyMetadata flag is enabled.\n\n`-ignoreIndividuals`: Individuals will not be included in the documentation.\n\n`-includeAnnotationProperties`: Include annotation properties defined in your ontology in the documentation (by default they are not included)\n\n`-analytics CODE`: Add a code snippet for Google analytics to track your HTML documentation. You need to add your CODE next to the flag. For example: UA-1234\n\n`-doNotDisplaySerializations`: The serializations of the ontology will not be displayed.\n\n`-displayDirectImportsOnly`: Only those imported ontologies that are directly imported in the ontology being documented.\n\n`-rewriteBase PATH`: Change the default rewrite base path. The default value is \"/\". This flag can only be used with the htaccess option.\n\n`-excludeIntroduction`: Skip the introduction section in the documentation.\n\n`-uniteSections`: Write all HTML sections into a single HTML document.\n\n`-noPlaceHolderText`: Do not add any placeholder text (this will remove intro, abstract (if empty) and description sections).\n\n`--help`: Shows a help message and exits.\n\n" + }, + "source": "https://raw.githubusercontent.com/True///README.md", + "technique": "header_analysis" + } + ], + "version": [ + { + "confidence": 1, + "result": { + "type": "String", + "value": "v1.4.25" + }, + "source": "https://raw.githubusercontent.com/True///codemeta.json", + "technique": "code_parser" + } + ] +} \ No newline at end of file diff --git a/src/somef_core/test/test_description_parser 2.py b/src/somef_core/test/test_description_parser 2.py new file mode 100644 index 0000000..5a3351a --- /dev/null +++ b/src/somef_core/test/test_description_parser 2.py @@ -0,0 +1,90 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.description_parser import parse_description_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestDescriptionParser(unittest.TestCase): + + def test_description(self): + description_file_path = test_data_repositories + os.path.sep + "tidyverse" + os.path.sep + "DESCRIPTION" + result = Result() + + # metadata_result = parse_description_file(description_file_path, result, "https://example.org/DESCRIPTION") + + metadata_result = parse_description_file(description_file_path, result, description_file_path) + + # print(metadata_result.results) + + # print(metadata_result.results.get(constants.CAT_PACKAGE_ID, [])) + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 3, "Expected three authors") + self.assertEqual(authors_results[0]["result"]["value"],"Hadley Wickham", "First author name mismatch") + self.assertEqual(authors_results[1]["result"]["value"],"Winston Chang","Second author name mismatch") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "DESCRIPTION") + # self.assertEqual(package_results[0]["result"]["value"], "https://example.org/DESCRIPTION") + self.assertEqual(package_results[0]["result"]["value"], description_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "tidyverse") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "The 'tidyverse' is a set of packages that work in harmony\n because they share common data representations and 'API' design. This\n package is designed to make it easy to install and load multiple\n 'tidyverse' packages in a single step. Learn more about the\n 'tidyverse' at .") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT + file LICENSE") + self.assertEqual(license_results[0]["result"]["type"], constants.STRING) + + + def test_description_2(self): + description_file_path = test_data_repositories + os.path.sep + "ggplot2" + os.path.sep + "DESCRIPTION" + + result = Result() + + # metadata_result = parse_description_file(description_file_path, result, "https://example.org/DESCRIPTION") + metadata_result = parse_description_file(description_file_path, result, description_file_path) + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 11, "Expected 11 authors") + self.assertEqual(authors_results[1]["result"]["value"],"Winston Chang","Second author name mismatch") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + self.assertEqual(package_results[0]["result"]["value"], description_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "ggplot2") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT + file LICENSE") + self.assertEqual(license_results[0]["result"]["type"], constants.STRING) + + code_repository_results = metadata_result.results.get(constants.CAT_CODE_REPOSITORY, []) + self.assertTrue(len(code_repository_results) > 0, "No code repository found") + self.assertEqual(code_repository_results[0]["result"]["value"], "https://github.com/tidyverse/ggplot2") + + issue_tracker_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) + self.assertTrue(len(issue_tracker_results) > 0, "No issue tracker found") + self.assertEqual(issue_tracker_results[0]["result"]["value"], "https://github.com/tidyverse/ggplot2/issues") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_description_parser.py b/src/somef_core/test/test_description_parser.py new file mode 100644 index 0000000..5a3351a --- /dev/null +++ b/src/somef_core/test/test_description_parser.py @@ -0,0 +1,90 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.description_parser import parse_description_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestDescriptionParser(unittest.TestCase): + + def test_description(self): + description_file_path = test_data_repositories + os.path.sep + "tidyverse" + os.path.sep + "DESCRIPTION" + result = Result() + + # metadata_result = parse_description_file(description_file_path, result, "https://example.org/DESCRIPTION") + + metadata_result = parse_description_file(description_file_path, result, description_file_path) + + # print(metadata_result.results) + + # print(metadata_result.results.get(constants.CAT_PACKAGE_ID, [])) + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 3, "Expected three authors") + self.assertEqual(authors_results[0]["result"]["value"],"Hadley Wickham", "First author name mismatch") + self.assertEqual(authors_results[1]["result"]["value"],"Winston Chang","Second author name mismatch") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "DESCRIPTION") + # self.assertEqual(package_results[0]["result"]["value"], "https://example.org/DESCRIPTION") + self.assertEqual(package_results[0]["result"]["value"], description_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "tidyverse") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "The 'tidyverse' is a set of packages that work in harmony\n because they share common data representations and 'API' design. This\n package is designed to make it easy to install and load multiple\n 'tidyverse' packages in a single step. Learn more about the\n 'tidyverse' at .") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT + file LICENSE") + self.assertEqual(license_results[0]["result"]["type"], constants.STRING) + + + def test_description_2(self): + description_file_path = test_data_repositories + os.path.sep + "ggplot2" + os.path.sep + "DESCRIPTION" + + result = Result() + + # metadata_result = parse_description_file(description_file_path, result, "https://example.org/DESCRIPTION") + metadata_result = parse_description_file(description_file_path, result, description_file_path) + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 11, "Expected 11 authors") + self.assertEqual(authors_results[1]["result"]["value"],"Winston Chang","Second author name mismatch") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + self.assertEqual(package_results[0]["result"]["value"], description_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "ggplot2") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT + file LICENSE") + self.assertEqual(license_results[0]["result"]["type"], constants.STRING) + + code_repository_results = metadata_result.results.get(constants.CAT_CODE_REPOSITORY, []) + self.assertTrue(len(code_repository_results) > 0, "No code repository found") + self.assertEqual(code_repository_results[0]["result"]["value"], "https://github.com/tidyverse/ggplot2") + + issue_tracker_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) + self.assertTrue(len(issue_tracker_results) > 0, "No issue tracker found") + self.assertEqual(issue_tracker_results[0]["result"]["value"], "https://github.com/tidyverse/ggplot2/issues") + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_dockerfile_parser.py b/src/somef_core/test/test_dockerfile_parser.py new file mode 100644 index 0000000..fd95dfb --- /dev/null +++ b/src/somef_core/test/test_dockerfile_parser.py @@ -0,0 +1,190 @@ +import json +import os +import unittest +from pathlib import Path +from .. import somef_cli +from ..utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestDockerfileParser(unittest.TestCase): + + def test_issue_725(self): + """Checks if this repository has properties extracted from Dockerfile Fairwinds""" + + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + local_repo=test_data_repositories + "Fairwinds", + doc_src=None, + in_file=None, + output=test_data_path + "test_issue_725.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=False, + readme_only=False) + + text_file = open(test_data_path + "test_issue_725.json", "r") + data = text_file.read() + text_file.close() + json_content = json.loads(data) + + owners = json_content.get("owner", []) + + code_parser_owners = [ + entry["result"]["value"] + for entry in owners + if entry.get("technique") == "code_parser" + ] + + assert "FairwindsOps, Inc." in code_parser_owners, ( + "Expected owner 'FairwindsOps, Inc.' extracted from Dockerfile " + f"with technique 'code_parser'. Found: {code_parser_owners}" + ) + + descriptions = json_content.get("description", []) + docker_descriptions = [ + entry["result"]["value"] + for entry in descriptions + if entry.get("technique") == "code_parser" + ] + + expected_description = ( + "Nova is a cli tool to find outdated or deprecated Helm charts " + "running in your Kubernetes cluster." + ) + + assert expected_description in docker_descriptions, ( + "Expected description extracted from Dockerfile not found.\n" + f"Expected: {expected_description}\n" + f"Found: {docker_descriptions}" + ) + + documentation = json_content.get("documentation", []) + + doc_urls = [ + entry["result"]["value"] + for entry in documentation + if entry.get("technique") == "code_parser" + ] + + expected_doc = "https://nova.docs.fairwinds.com/" + + assert expected_doc in doc_urls, ( + f"Expected documentation URL '{expected_doc}' not found. " + f"Found: {doc_urls}" + ) + + authors = json_content.get("authors", []) + + author_values = [ + entry["result"]["value"] + for entry in authors + if entry.get("technique") == "code_parser" + ] + + expected_author = "FairwindsOps, Inc." + + assert expected_author in author_values, ( + f"Expected author '{expected_author}' not found. " + f"Authors found: {author_values}" + ) + os.remove(test_data_path + "test_issue_725.json") + + def test_issue_725_2(self): + """Checks if this repository has properties extracted from Dockerfile Prometeus""" + + somef_cli.run_cli(threshold=0.8, + ignore_classifiers=False, + repo_url=None, + local_repo=test_data_repositories + "Prometeus", + doc_src=None, + in_file=None, + output=test_data_path + "test_issue_725_2.json", + graph_out=None, + graph_format="turtle", + codemeta_out=None, + pretty=True, + missing=False, + readme_only=False) + + text_file = open(test_data_path + "test_issue_725_2.json", "r") + data = text_file.read() + text_file.close() + json_content = json.loads(data) + + code_repos = json_content.get("code_repository", []) + code_parser_repos = [ + entry["result"]["value"] + for entry in code_repos + if entry.get("technique") == "code_parser" + ] + + expected_repo = "https://github.com/prometheus/prometheus" + + assert expected_repo in code_parser_repos, ( + f"Expected code_repository '{expected_repo}' extracted with technique " + f"'code_parser'. Found: {code_parser_repos}" + ) + + licenses = json_content.get("license", []) + code_parser_licenses = [ + entry["result"] + for entry in licenses + if entry.get("technique") == "code_parser" + ] + + assert any( + lic.get("spdx_id") == "Apache-2.0" + for lic in code_parser_licenses + ), ( + "Expected license with SPDX ID 'Apache-2.0' extracted from Dockerfile " + f"using 'code_parser'. Found: {code_parser_licenses}" + ) + + descriptions = json_content.get("description", []) + code_parser_descriptions = [ + entry["result"]["value"] + for entry in descriptions + if entry.get("technique") == "code_parser" + ] + + expected_description = "The Prometheus monitoring system and time series database" + assert expected_description in code_parser_descriptions, ( + "Expected description extracted from Dockerfile not found.\n" + f"Expected: {expected_description}\n" + f"Found: {code_parser_descriptions}" + ) + + names = json_content.get("name", []) + code_parser_names = [ + entry["result"]["value"] + for entry in names + if entry.get("technique") == "code_parser" + ] + + expected_name = "Prometheus" + assert expected_name in code_parser_names, ( + f"Expected name '{expected_name}' extracted from Dockerfile " + f"using 'code_parser'. Found: {code_parser_names}" + ) + + documentation = json_content.get("documentation", []) + code_parser_docs = [ + entry["result"]["value"] + for entry in documentation + if entry.get("technique") == "code_parser" + ] + + expected_doc = "https://prometheus.io/docs" + assert expected_doc in code_parser_docs, ( + f"Expected documentation URL '{expected_doc}' extracted from Dockerfile " + f"using 'code_parser'. Found: {code_parser_docs}" + ) + os.remove(test_data_path + "test_issue_725_2.json") + +if __name__ == '__main__': + unittest.main() diff --git a/src/somef_core/test/test_extract_authors 2.py b/src/somef_core/test/test_extract_authors 2.py new file mode 100644 index 0000000..b1b34eb --- /dev/null +++ b/src/somef_core/test/test_extract_authors 2.py @@ -0,0 +1,71 @@ +import unittest +from pathlib import Path +from .. parser import authors_parser + +test_data_repositories = Path(__file__).parent / "test_data" / "authors_files" + +class TestExtractAuthors(unittest.TestCase): + + def test_extract_authors_files(self): + + """This test checks if a file ot authors containing the correct values""" + for file_path in test_data_repositories.glob("*"): + str_authors = "" + if file_path.is_file(): + file_name = file_path.stem + prefix = file_name.split("_AUTHORS")[0] + + with open(file_path, "r", encoding="utf-8") as f: + str_authors = f.read() + authors_list = authors_parser.parse_author_file(str_authors) + + if prefix == "docker": + assert len(authors_list) == 715, f"Expected 215 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("given_name") == "Aanand", f"First author given_name incorrect: {first_author.get('given_name')}" + assert first_author.get("last_name") == "Prasad", f"First author last_name incorrect: {first_author.get('last_name')}" + assert first_author.get("email") == "aanand.prasad@gmail.com", f"First author email incorrect: {first_author.get('email')}" + assert any(a.get("name") == "Daan van Berkel" for a in authors_list), "Expected author 'Daan van Berkel' not found" + last_author = authors_list[-1] + assert last_author.get("email") == "jifeng.yin@gmail.com", f"Last author email incorrect: {last_author.get('email')}" + + elif prefix == "tensorFlow": + assert len(authors_list) == 3, f"Expected 3 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("type") == "Organization", f"First author type incorrect: {first_author.get('type')}" + assert first_author.get("name") == "Google Inc.", f"First author name incorrect: {first_author.get('name')}" + found = False + for author in authors_list: + if ( + author.get("email") == "terrytangyuan@gmail.com" + and author.get("last_name") == "Tang" + ): + found = True + break + assert found, "Expected author with email terrytangyuan@gmail.com and last_name Tang not found" + + elif prefix == "ireeOrg": + assert len(authors_list) == 3, f"Expected 3 authors, got {len(authors_list)}" + + for i, author in enumerate(authors_list): + assert author.get("type") == "Organization", f"Author {i} is not an Organization: {author}" + + last_author = authors_list[-1] + assert last_author.get("name") == "Advanced Micro Devices, Inc.", ( + f"Last author name incorrect: {last_author.get('name')}" + ) + + elif prefix == "jetBrain": + assert len(authors_list) == 2, f"Expected 2 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("last_name") == "Nurullin", f"First author last_name incorrect: {first_author.get('last_name')}" + + elif prefix == "pluginsGLPI": + assert len(authors_list) == 1, f"Expected 1 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("name") == "Julien Dombre", f"First author name incorrect: {first_author.get('last_name')}" + + + + + diff --git a/src/somef_core/test/test_extract_authors.py b/src/somef_core/test/test_extract_authors.py new file mode 100644 index 0000000..b1b34eb --- /dev/null +++ b/src/somef_core/test/test_extract_authors.py @@ -0,0 +1,71 @@ +import unittest +from pathlib import Path +from .. parser import authors_parser + +test_data_repositories = Path(__file__).parent / "test_data" / "authors_files" + +class TestExtractAuthors(unittest.TestCase): + + def test_extract_authors_files(self): + + """This test checks if a file ot authors containing the correct values""" + for file_path in test_data_repositories.glob("*"): + str_authors = "" + if file_path.is_file(): + file_name = file_path.stem + prefix = file_name.split("_AUTHORS")[0] + + with open(file_path, "r", encoding="utf-8") as f: + str_authors = f.read() + authors_list = authors_parser.parse_author_file(str_authors) + + if prefix == "docker": + assert len(authors_list) == 715, f"Expected 215 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("given_name") == "Aanand", f"First author given_name incorrect: {first_author.get('given_name')}" + assert first_author.get("last_name") == "Prasad", f"First author last_name incorrect: {first_author.get('last_name')}" + assert first_author.get("email") == "aanand.prasad@gmail.com", f"First author email incorrect: {first_author.get('email')}" + assert any(a.get("name") == "Daan van Berkel" for a in authors_list), "Expected author 'Daan van Berkel' not found" + last_author = authors_list[-1] + assert last_author.get("email") == "jifeng.yin@gmail.com", f"Last author email incorrect: {last_author.get('email')}" + + elif prefix == "tensorFlow": + assert len(authors_list) == 3, f"Expected 3 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("type") == "Organization", f"First author type incorrect: {first_author.get('type')}" + assert first_author.get("name") == "Google Inc.", f"First author name incorrect: {first_author.get('name')}" + found = False + for author in authors_list: + if ( + author.get("email") == "terrytangyuan@gmail.com" + and author.get("last_name") == "Tang" + ): + found = True + break + assert found, "Expected author with email terrytangyuan@gmail.com and last_name Tang not found" + + elif prefix == "ireeOrg": + assert len(authors_list) == 3, f"Expected 3 authors, got {len(authors_list)}" + + for i, author in enumerate(authors_list): + assert author.get("type") == "Organization", f"Author {i} is not an Organization: {author}" + + last_author = authors_list[-1] + assert last_author.get("name") == "Advanced Micro Devices, Inc.", ( + f"Last author name incorrect: {last_author.get('name')}" + ) + + elif prefix == "jetBrain": + assert len(authors_list) == 2, f"Expected 2 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("last_name") == "Nurullin", f"First author last_name incorrect: {first_author.get('last_name')}" + + elif prefix == "pluginsGLPI": + assert len(authors_list) == 1, f"Expected 1 authors, got {len(authors_list)}" + first_author = authors_list[0] + assert first_author.get("name") == "Julien Dombre", f"First author name incorrect: {first_author.get('last_name')}" + + + + + diff --git a/src/somef_core/test/test_extract_workflows 2.py b/src/somef_core/test/test_extract_workflows 2.py new file mode 100644 index 0000000..ba8a79b --- /dev/null +++ b/src/somef_core/test/test_extract_workflows 2.py @@ -0,0 +1,18 @@ +import unittest +import os +from pathlib import Path + +from .. import extract_workflows + +test_data_repositories = str(Path(__file__).parent / "test_data") + os.path.sep + + +class TestWorkflows(unittest.TestCase): + def test_is_workflow(self): + workflow = extract_workflows.is_file_workflow(test_data_repositories + "SimulatedReads2Map.wdl") + assert workflow, "The file does contain a workflow." + + def test_is_workflow_fake(self): + workflow = extract_workflows.is_file_workflow( + test_data_repositories + "repositories/wav2letter/scripts/arrayfire_parser.py") + assert (workflow is False) diff --git a/src/somef_core/test/test_extract_workflows.py b/src/somef_core/test/test_extract_workflows.py new file mode 100644 index 0000000..ba8a79b --- /dev/null +++ b/src/somef_core/test/test_extract_workflows.py @@ -0,0 +1,18 @@ +import unittest +import os +from pathlib import Path + +from .. import extract_workflows + +test_data_repositories = str(Path(__file__).parent / "test_data") + os.path.sep + + +class TestWorkflows(unittest.TestCase): + def test_is_workflow(self): + workflow = extract_workflows.is_file_workflow(test_data_repositories + "SimulatedReads2Map.wdl") + assert workflow, "The file does contain a workflow." + + def test_is_workflow_fake(self): + workflow = extract_workflows.is_file_workflow( + test_data_repositories + "repositories/wav2letter/scripts/arrayfire_parser.py") + assert (workflow is False) diff --git a/src/somef_core/test/test_gemspec_parser 2.py b/src/somef_core/test/test_gemspec_parser 2.py new file mode 100644 index 0000000..f9c4258 --- /dev/null +++ b/src/somef_core/test/test_gemspec_parser 2.py @@ -0,0 +1,77 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.gemspec_parser import parse_gemspec_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestGemSpecParser(unittest.TestCase): + + def test_parse_gemspec(self): + gemspec_file_path = test_data_repositories + os.path.sep + "bootstrap-datepicker-rails" + os.path.sep + "bootstrap-datepicker-rails.gemspec" + result = Result() + + # metadata_result = parse_gemspec_file(gemspec_file_path, result, "https://example.org/bootstrap-datepicker-rails.gemspec") + metadata_result = parse_gemspec_file(gemspec_file_path, result, gemspec_file_path) + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 2, "Expected two authors") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bootstrap-datepicker-rails.gemspec") + self.assertEqual(package_results[0]["result"]["value"], gemspec_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "bootstrap-datepicker-rails") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "A date picker for Twitter Bootstrap") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "https://github.com/Nerian/bootstrap-datepicker-rails") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + found_jquery = False + found_bootstrap = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "railties" and dependency.get("dependency_type") == "runtime": + found_jquery = True + + self.assertTrue(found_jquery, "Dependency not found") + + def test_parse_gemspec_another_authors(self): + gemspec_file_path = test_data_repositories + os.path.sep + "bootstrap-datepicker-rails" + os.path.sep + "bootstrap-datepicker-rails-2.gemspec" + result = Result() + + metadata_result = parse_gemspec_file(gemspec_file_path, result, "https://example.org/bootstrap-datepicker-rails.gemspec") + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 1, "Expected one authors") + self.assertEqual(authors_results[0]["result"]["value"], "Gonzalo Rodríguez-Baltanás Díaz") + + + # To do Version + # To do Email + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_gemspec_parser.py b/src/somef_core/test/test_gemspec_parser.py new file mode 100644 index 0000000..f9c4258 --- /dev/null +++ b/src/somef_core/test/test_gemspec_parser.py @@ -0,0 +1,77 @@ +import unittest +import os +from pathlib import Path + +from somef_core.parser.gemspec_parser import parse_gemspec_file +from somef_core.process_results import Result +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestGemSpecParser(unittest.TestCase): + + def test_parse_gemspec(self): + gemspec_file_path = test_data_repositories + os.path.sep + "bootstrap-datepicker-rails" + os.path.sep + "bootstrap-datepicker-rails.gemspec" + result = Result() + + # metadata_result = parse_gemspec_file(gemspec_file_path, result, "https://example.org/bootstrap-datepicker-rails.gemspec") + metadata_result = parse_gemspec_file(gemspec_file_path, result, gemspec_file_path) + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 2, "Expected two authors") + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "bootstrap-datepicker-rails.gemspec") + self.assertEqual(package_results[0]["result"]["value"], gemspec_file_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + + id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(id_results) > 0, "No identifier found") + self.assertEqual(id_results[0]["result"]["value"], "bootstrap-datepicker-rails") + self.assertEqual(id_results[0]["result"]["type"], constants.STRING) + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "A date picker for Twitter Bootstrap") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + homepage_results = metadata_result.results.get(constants.CAT_HOMEPAGE, []) + self.assertTrue(len(homepage_results) > 0, "No homepage found") + self.assertEqual(homepage_results[0]["result"]["value"], "https://github.com/Nerian/bootstrap-datepicker-rails") + self.assertEqual(homepage_results[0]["result"]["type"], constants.URL) + + license_results = metadata_result.results.get(constants.CAT_LICENSE, []) + self.assertTrue(len(license_results) > 0, "No license found") + self.assertEqual(license_results[0]["result"]["value"], "MIT") + self.assertEqual(license_results[0]["result"]["type"], constants.LICENSE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + found_jquery = False + found_bootstrap = False + for req_result in requirements_results: + dependency = req_result["result"] + if dependency.get("name") == "railties" and dependency.get("dependency_type") == "runtime": + found_jquery = True + + self.assertTrue(found_jquery, "Dependency not found") + + def test_parse_gemspec_another_authors(self): + gemspec_file_path = test_data_repositories + os.path.sep + "bootstrap-datepicker-rails" + os.path.sep + "bootstrap-datepicker-rails-2.gemspec" + result = Result() + + metadata_result = parse_gemspec_file(gemspec_file_path, result, "https://example.org/bootstrap-datepicker-rails.gemspec") + + authors_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(authors_results) == 1, "Expected one authors") + self.assertEqual(authors_results[0]["result"]["value"], "Gonzalo Rodríguez-Baltanás Díaz") + + + # To do Version + # To do Email + +if __name__ == "__main__": + unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_gitlab_selfhosted.py b/src/somef_core/test/test_gitlab_selfhosted.py index 3607432..8fe47ce 100644 --- a/src/somef_core/test/test_gitlab_selfhosted.py +++ b/src/somef_core/test/test_gitlab_selfhosted.py @@ -10,16 +10,17 @@ class TestGitlabSelfHosted(unittest.TestCase): def test_gitlab_self_hosted(self): - """Checks if SOMEF works against server self_hosted Gitlab . Full analysis""" - somef_cli.run_cli(threshold=0.8, - repo_url="https://gitlab.in2p3.fr/gammalearn/gammalearn", - output=test_data_path + "test-self-hosted-gitlab.json", - pretty=True, - readme_only=False) - text_file = open(test_data_path + "test-self-hosted-gitlab.json", "r") - data = text_file.read() - text_file.close() - json_content = json.loads(data) - download = json_content[constants.CAT_DOWNLOAD_URL] - assert download is not None - os.remove(test_data_path + "test-self-hosted-gitlab.json") \ No newline at end of file + + """Checks if SOMEF works against server self_hosted Gitlab . Full analysis""" + somef_cli.run_cli(threshold=0.8, + repo_url="https://gitlab.in2p3.fr/gammalearn/gammalearn", + output=test_data_path + "test-self-hosted-gitlab.json", + pretty=True, + readme_only=False) + text_file = open(test_data_path + "test-self-hosted-gitlab.json", "r") + data = text_file.read() + text_file.close() + json_content = json.loads(data) + download = json_content[constants.CAT_DOWNLOAD_URL] + assert download is not None + os.remove(test_data_path + "test-self-hosted-gitlab.json") \ No newline at end of file diff --git a/src/somef_core/test/test_package_json_parser.py b/src/somef_core/test/test_package_json_parser.py index 062aeb4..6e9de96 100644 --- a/src/somef_core/test/test_package_json_parser.py +++ b/src/somef_core/test/test_package_json_parser.py @@ -4,9 +4,9 @@ from nltk.sem.hole import Constants -from somef.parser.package_json_parser import parse_package_json_file -from somef.process_results import Result -from somef.utils import constants +from somef_core.parser.package_json_parser import parse_package_json_file +from somef_core.process_results import Result +from somef_core.utils import constants test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep @@ -16,8 +16,8 @@ def test_parse_package_json_file(self): package_file_path = test_data_path + "package_neors.json" result = Result() - metadata_result = parse_package_json_file(package_file_path, result, "http://example.com/package_neors.json") - + # metadata_result = parse_package_json_file(package_file_path, result, "http://example.com/package_neors.json") + metadata_result = parse_package_json_file(package_file_path, result, package_file_path) package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) self.assertTrue(len(package_id_results) > 0, "No package ID found") self.assertEqual(package_id_results[0]["result"]["value"], "jsonlab") @@ -58,14 +58,67 @@ def test_parse_package_json_file(self): package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) self.assertTrue(len(package_results) > 0, "No package file info found") - self.assertEqual(package_results[0]["result"]["value"], "package.json") + # self.assertEqual(package_results[0]["result"]["value"], "package.json") + # self.assertEqual(package_results[0]["result"]["value"], "http://example.com/package_neors.json") + self.assertEqual(package_results[0]["result"]["value"],package_file_path) self.assertEqual(package_results[0]["result"]["type"], constants.URL) keywords_results = metadata_result.results.get(constants.CAT_KEYWORDS, []) self.assertEqual(len(keywords_results), 0, "Keywords should not be found in this package.json") + + # requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + # self.assertEqual(len(requirements_results), 0, "No dependencies should be found in this package.json") requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) - self.assertEqual(len(requirements_results), 0, "No dependencies should be found in this package.json") + self.assertEqual(len(requirements_results), 3, "Expected three requirements") + self.assertEqual(requirements_results[0]["result"]["name"], "foo", "First requirement name mismatch") + + def test_parse_package_json_file_2(self): + package_file_path = test_data_path + "package_npm.json" + result = Result() + + metadata_result = parse_package_json_file(package_file_path, result, "http://example.com/package_npm.json") + + package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id_results) > 0, "No package ID found") + self.assertEqual(package_id_results[0]["result"]["value"], "npm") + self.assertEqual(package_id_results[0]["result"]["type"], constants.STRING) + self.assertEqual(package_id_results[0]["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertEqual(version_results[0]["result"]["value"], "11.6.2") + + description_results = metadata_result.results.get(constants.CAT_DESCRIPTION, []) + self.assertTrue(len(description_results) > 0, "No description found") + self.assertEqual(description_results[0]["result"]["value"], "a package manager for JavaScript") + self.assertEqual(description_results[0]["result"]["type"], constants.STRING) + + repo_results = metadata_result.results.get(constants.CAT_CODE_REPOSITORY, []) + self.assertTrue(len(repo_results) > 0, "No repository found") + self.assertEqual(repo_results[0]["result"]["value"], "git+https://github.com/npm/cli.git") + self.assertEqual(repo_results[0]["result"]["type"], constants.URL) + + issue_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) + self.assertTrue(len(issue_results) > 0, "No issue tracker found") + self.assertEqual(issue_results[0]["result"]["value"], "https://github.com/npm/cli/issues") + self.assertEqual(issue_results[0]["result"]["type"], constants.URL) + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(author_results) > 0, "No author found") + self.assertEqual(author_results[0]["result"]["type"], constants.AGENT) + self.assertEqual(author_results[0]["result"]["value"], "GitHub Inc.") + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertEqual(len(requirements_results), 85, "Expected 85 requirements") + self.assertEqual(requirements_results[0]["result"]["name"], "@isaacs/string-locale-compare", "First requirement name mismatch") + self.assertEqual(requirements_results[0]["result"]["version"], "^1.1.0", "First requirement version mismatch") + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertEqual(len(runtime_results), 1, "Expected one runtime platform") + self.assertEqual(runtime_results[0]["result"]["name"], "Node", "Expected Node as runtime platform") + self.assertEqual(runtime_results[0]["result"]["version"], "^20.17.0 || >=22.9.0", "Wrong version") + + if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_parser_somef.py b/src/somef_core/test/test_parser_somef.py index 0ed2c2b..da36eb9 100644 --- a/src/somef_core/test/test_parser_somef.py +++ b/src/somef_core/test/test_parser_somef.py @@ -2,7 +2,7 @@ import os from pathlib import Path -from somef.parser.mardown_parser import extract_headers, extract_headers_with_tags, extract_content_per_header, \ +from somef_core.parser.mardown_parser import extract_headers, extract_headers_with_tags, extract_content_per_header, \ extract_bash, extract_blocks_excerpts, extract_text_excerpts_header, extract_headers_parents, is_header # Test data for tests diff --git a/src/somef_core/test/test_pom_parser.py b/src/somef_core/test/test_pom_parser.py index e0ce993..52e8d2f 100644 --- a/src/somef_core/test/test_pom_parser.py +++ b/src/somef_core/test/test_pom_parser.py @@ -2,9 +2,10 @@ import os from pathlib import Path -from somef.parser.pom_xml_parser import parse_pom_file -from somef.process_results import Result -from somef.utils import constants +from somef_core.parser.pom_xml_parser import parse_pom_file +from somef_core.parser import pom_xml_parser +from somef_core.process_results import Result +from somef_core.utils import constants # Test data for tests test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep @@ -13,10 +14,11 @@ class TestPomParser(unittest.TestCase): def test_parse_pom_file(self): + pom_xml_parser.processed_pom = False pom_file_path = test_data_repositories + os.path.sep + "Widoco" + os.path.sep + "pom.xml" result = Result() - - metadata_result = parse_pom_file(pom_file_path, result, "https://example.org/pom.xml") + + metadata_result = parse_pom_file(pom_file_path, result, pom_file_path) identifier_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) self.assertTrue(len(identifier_results) > 0, "No identifier found") @@ -32,7 +34,8 @@ def test_parse_pom_file(self): package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) self.assertTrue(len(package_results) > 0, "No package file info found") - self.assertEqual(package_results[0]["result"]["value"], "pom.xml") + # self.assertEqual(package_results[0]["result"]["value"], "pom.xml") + self.assertEqual(package_results[0]["result"]["value"], pom_file_path) self.assertEqual(package_results[0]["result"]["type"], constants.URL) requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) @@ -50,19 +53,20 @@ def test_parse_pom_file(self): repo_results = metadata_result.results.get(constants.CAT_PACKAGE_DISTRIBUTION, []) self.assertTrue(len(repo_results) > 0, "No repository information found") - - repos = repo_results[0]["result"]["value"] - found_jitpack = False - for repo in repos: - if repo.get("id") == "jitpack.io": - found_jitpack = True - self.assertEqual(repo.get("url"), "https://jitpack.io") - break - self.assertTrue(found_jitpack, "jitpack.io repository not found") + repos = repo_results[1]["result"] + # found_jitpack = False + value = repos.get("value", None) + url = repos.get("url", None) + + self.assertEqual(value, "jitpack.io", "jitpack.io repository not found") + self.assertEqual(url, "https://jitpack.io", "url jitpack.io repository not found") + scm_results = [r for r in metadata_result.results.get(constants.CAT_PACKAGE_DISTRIBUTION, []) if r["result"].get("type") == "url" and isinstance(r["result"]["value"], str)] - self.assertEqual(len(scm_results), 0, "SCM URL should not exist in this POM") + + # self.assertEqual(len(scm_results), 0, "SCM URL should not exist in this POM") + self.assertEqual(len(scm_results), 0, "Expected one package distribution from SCM URL") issue_results = metadata_result.results.get(constants.CAT_ISSUE_TRACKER, []) self.assertEqual(len(issue_results), 0, "Issue tracker should not exist in this POM") @@ -73,5 +77,42 @@ def test_parse_pom_file(self): license_results = metadata_result.results.get(constants.CAT_LICENSE, []) self.assertEqual(len(license_results), 0, "No licenses should be found in this POM") + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertEqual(runtime_results[0]["result"]["name"], "Java") + + + def test_parse_pom_file_2(self): + pom_xml_parser.processed_pom = False + pom_file_path = test_data_repositories + os.path.sep + "maven" + os.path.sep + "pom.xml" + result = Result() + + metadata_result = parse_pom_file(pom_file_path, result, "https://example2.org/pom.xml") + identifier_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(identifier_results) > 0, "No identifier found") + self.assertEqual(identifier_results[0]["result"]["value"], ".maven") + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertTrue(len(version_results) > 0, "No version found") + self.assertEqual(version_results[0]["result"]["value"], "4.1.0-SNAPSHOT") + self.assertEqual(version_results[0]["result"]["type"], constants.RELEASE) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + self.assertEqual(requirements_results[2]["result"]["value"], "org.apache.maven.maven-jline") + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + + self.assertEqual(len(author_results), 0, "No authors should be found in this POM") + + scm_results = [r for r in metadata_result.results.get(constants.CAT_PACKAGE_DISTRIBUTION, []) + if r["result"].get("type") == "url" and isinstance(r["result"]["value"], str)] + # because url is https://github.com/apache/maven/tree/${project.scm.tag} and is not permited '${project.scm.tag}' + self.assertEqual(len(scm_results), 0, "Expected one package distribution from SCM URL") + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertTrue(len(runtime_results) > 0, "No runtime found") + self.assertEqual(runtime_results[0]["result"]["name"], "Java") + self.assertEqual(runtime_results[0]["result"]["version"], "17") + if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_process_repository.py b/src/somef_core/test/test_process_repository.py index 84b0e54..657f895 100644 --- a/src/somef_core/test/test_process_repository.py +++ b/src/somef_core/test/test_process_repository.py @@ -182,7 +182,9 @@ def test_issue_526(self): github_data = Result() text, github_data = process_files.process_repository_files(test_data_repositories + "Widoco", github_data, constants.RepositoryType.LOCAL) - assert len(github_data.results[constants.CAT_CITATION]) == 1 + # after solving issue refernce_publication it must be 2 citations in results citation. + # assert len(github_data.results[constants.CAT_CITATION]) == 1 + assert len(github_data.results[constants.CAT_CITATION]) == 2 def test_issue_530(self): """ @@ -194,6 +196,6 @@ def test_issue_530(self): constants.RepositoryType.LOCAL) licenses = github_data.results[constants.CAT_LICENSE] citation = github_data.results[constants.CAT_CITATION] - assert len(licenses) == 1 and "LICENSE" in licenses[0]["source"] and \ + # there are two licenses because the codemeta parser obtains one + assert len(licenses) == 2 and "LICENSE" or "codemeta" in licenses[0]["source"] and \ len(citation) == 1 and "example_onto" not in citation[0]["source"] - \ No newline at end of file diff --git a/src/somef_core/test/test_publiccode_parser 2.py b/src/somef_core/test/test_publiccode_parser 2.py new file mode 100644 index 0000000..4c4445e --- /dev/null +++ b/src/somef_core/test/test_publiccode_parser 2.py @@ -0,0 +1,144 @@ +import unittest +import os +from pathlib import Path +from somef_core.process_results import Result +from somef_core.parser.publiccode_parser import parse_publiccode_file + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestPubliccodeParser(unittest.TestCase): + + def test_issue_733(self): + + """Checks if this repository has properties extracted from publiccode.yaml. MaykinMedia repository""" + publiccode_file_path = test_data_repositories + os.path.sep + "maykinMedia" + os.path.sep + "publiccode.yaml" + result = Result() + + metadata_result = parse_publiccode_file( + publiccode_file_path, + result, + publiccode_file_path + ) + # print("Metadata results:", metadata_result.results) + platform = metadata_result.results.get("runtime_platform", []) + code_parser_platforms = [ + entry["result"]["value"] + for entry in platform + if entry.get("technique") == "code_parser" + ] + + assert "web" in code_parser_platforms, ( + "Expected platform 'web' extracted from publiccode.yaml " + f"with technique 'code_parser'. Found: {code_parser_platforms}" + ) + + code_repos = [entry["result"]["value"] for entry in metadata_result.results.get("code_repository", [])] + assert "http://github.com/maykinmedia/objects-api.git" in code_repos + + app_domains = [entry["result"]["value"] for entry in metadata_result.results.get("application_domain", [])] + expected_domains = ["data-collection", "it-development"] + for domain in expected_domains: + assert domain in app_domains + + requirements = metadata_result.results.get("requirements", []) + + req_map = {entry["result"]["name"]: entry["result"]["version"] for entry in requirements} + assert req_map["Objecttypes API"] == ">=1.0" + assert req_map["PostgreSQL"] == ">=14.0" + + version = metadata_result.results.get("version", []) + self.assertEqual(version[0]["result"]["value"], "3.5.0") + + descriptions = metadata_result.results.get("description", []) + self.assertTrue(len(descriptions) > 3, "Must be at least four descriptions found") + self.assertEqual(descriptions[0]["result"]["value"], 'API voor het beheren van objecten') + + name = metadata_result.results.get("name", []) + self.assertEqual(name[0]["result"]["value"], "Objects API") + + keywords_values = metadata_result.results.get("keywords", []) + self.assertTrue(keywords_values) + keywords = keywords_values[0]["result"]["value"] + self.assertEqual(keywords[1],"Minimalistische objecten beheerinterface") + self.assertEqual(keywords[3],"Minimalistic object management interface") + + development_status = metadata_result.results.get("development_status", []) + self.assertEqual(development_status[0]["result"]["value"], 'beta') + + licenses = metadata_result.results.get("license", []) + self.assertEqual(licenses[0]["result"]["value"], 'EUPL-1.2') + date_updated = metadata_result.results.get("date_updated", []) + self.assertEqual(date_updated[0]["result"]["value"], '2025-12-01') + + owners = metadata_result.results.get("owner", []) + self.assertEqual(owners[0]["result"]["email"], 'info@maykinmedia.nl') + self.assertEqual(owners[1]["result"]["value"], 'Joeri Bekker') + + def test_issue_733_2(self): + + """Checks if this repository has properties extracted from publiccode.yaml Example publiccode repository""" + publiccode_file_path = test_data_repositories + os.path.sep + "publicCode-Example" + os.path.sep + "publiccode.yml" + result = Result() + + metadata_result = parse_publiccode_file( + publiccode_file_path, + result, + publiccode_file_path + ) + # print("Metadata results:", metadata_result.results) + platform = metadata_result.results.get("runtime_platform", []) + code_parser_platforms = [ + entry["result"]["value"] + for entry in platform + if entry.get("technique") == "code_parser" + ] + + assert "android" in code_parser_platforms, ( + "Expected platform 'android' extracted from publiccode.yaml " + f"with technique 'code_parser'. Found: {code_parser_platforms}" + ) + + code_repos = [entry["result"]["value"] for entry in metadata_result.results.get("code_repository", [])] + assert "https://example.com/italia/medusa.git" in code_repos + + app_domains = [entry["result"]["value"] for entry in metadata_result.results.get("application_domain", [])] + expected_domains = ["content-management", "office"] + for domain in expected_domains: + assert domain in app_domains + + requirements = metadata_result.results.get("requirements", []) + + req_map = {entry["result"]["name"]: entry["result"]["version"] for entry in requirements} + assert req_map["MySQL"] == ">=1.1,<1.3" + assert req_map["PostgreSQL"] == "3.2" + assert req_map["Oracle"] == ">=11.4" + assert req_map["IBM SoftLayer"] is None + assert req_map["NFC Reader"] is None + + version = metadata_result.results.get("version", []) + self.assertEqual(version[0]["result"]["value"], "1.0") + + descriptions = metadata_result.results.get("description", []) + self.assertTrue(len(descriptions) > 1, "Must be at least two descriptions found") + self.assertEqual(descriptions[0]["result"]["value"], 'This description can have a maximum 150 characters long. We should not fill the remaining space with "Lorem Ipsum". End') + + name = metadata_result.results.get("name", []) + self.assertEqual(name[0]["result"]["value"], "Medusa") + + keywords_values = metadata_result.results.get("keywords", []) + self.assertTrue(keywords_values) + keywords = keywords_values[0]["result"]["value"] + self.assertEqual(keywords[1],"Will run without a problem") + self.assertEqual(keywords[2],"Has zero bugs") + + development_status = metadata_result.results.get("development_status", []) + self.assertEqual(development_status[0]["result"]["value"], 'development') + + licenses = metadata_result.results.get("license", []) + print(licenses) + self.assertEqual(licenses[0]["result"]["spdx_id"], 'AGPL-3.0') + date_updated = metadata_result.results.get("date_updated", []) + self.assertEqual(date_updated[0]["result"]["value"], '2017-04-15') + + diff --git a/src/somef_core/test/test_publiccode_parser.py b/src/somef_core/test/test_publiccode_parser.py new file mode 100644 index 0000000..4c4445e --- /dev/null +++ b/src/somef_core/test/test_publiccode_parser.py @@ -0,0 +1,144 @@ +import unittest +import os +from pathlib import Path +from somef_core.process_results import Result +from somef_core.parser.publiccode_parser import parse_publiccode_file + +test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + +class TestPubliccodeParser(unittest.TestCase): + + def test_issue_733(self): + + """Checks if this repository has properties extracted from publiccode.yaml. MaykinMedia repository""" + publiccode_file_path = test_data_repositories + os.path.sep + "maykinMedia" + os.path.sep + "publiccode.yaml" + result = Result() + + metadata_result = parse_publiccode_file( + publiccode_file_path, + result, + publiccode_file_path + ) + # print("Metadata results:", metadata_result.results) + platform = metadata_result.results.get("runtime_platform", []) + code_parser_platforms = [ + entry["result"]["value"] + for entry in platform + if entry.get("technique") == "code_parser" + ] + + assert "web" in code_parser_platforms, ( + "Expected platform 'web' extracted from publiccode.yaml " + f"with technique 'code_parser'. Found: {code_parser_platforms}" + ) + + code_repos = [entry["result"]["value"] for entry in metadata_result.results.get("code_repository", [])] + assert "http://github.com/maykinmedia/objects-api.git" in code_repos + + app_domains = [entry["result"]["value"] for entry in metadata_result.results.get("application_domain", [])] + expected_domains = ["data-collection", "it-development"] + for domain in expected_domains: + assert domain in app_domains + + requirements = metadata_result.results.get("requirements", []) + + req_map = {entry["result"]["name"]: entry["result"]["version"] for entry in requirements} + assert req_map["Objecttypes API"] == ">=1.0" + assert req_map["PostgreSQL"] == ">=14.0" + + version = metadata_result.results.get("version", []) + self.assertEqual(version[0]["result"]["value"], "3.5.0") + + descriptions = metadata_result.results.get("description", []) + self.assertTrue(len(descriptions) > 3, "Must be at least four descriptions found") + self.assertEqual(descriptions[0]["result"]["value"], 'API voor het beheren van objecten') + + name = metadata_result.results.get("name", []) + self.assertEqual(name[0]["result"]["value"], "Objects API") + + keywords_values = metadata_result.results.get("keywords", []) + self.assertTrue(keywords_values) + keywords = keywords_values[0]["result"]["value"] + self.assertEqual(keywords[1],"Minimalistische objecten beheerinterface") + self.assertEqual(keywords[3],"Minimalistic object management interface") + + development_status = metadata_result.results.get("development_status", []) + self.assertEqual(development_status[0]["result"]["value"], 'beta') + + licenses = metadata_result.results.get("license", []) + self.assertEqual(licenses[0]["result"]["value"], 'EUPL-1.2') + date_updated = metadata_result.results.get("date_updated", []) + self.assertEqual(date_updated[0]["result"]["value"], '2025-12-01') + + owners = metadata_result.results.get("owner", []) + self.assertEqual(owners[0]["result"]["email"], 'info@maykinmedia.nl') + self.assertEqual(owners[1]["result"]["value"], 'Joeri Bekker') + + def test_issue_733_2(self): + + """Checks if this repository has properties extracted from publiccode.yaml Example publiccode repository""" + publiccode_file_path = test_data_repositories + os.path.sep + "publicCode-Example" + os.path.sep + "publiccode.yml" + result = Result() + + metadata_result = parse_publiccode_file( + publiccode_file_path, + result, + publiccode_file_path + ) + # print("Metadata results:", metadata_result.results) + platform = metadata_result.results.get("runtime_platform", []) + code_parser_platforms = [ + entry["result"]["value"] + for entry in platform + if entry.get("technique") == "code_parser" + ] + + assert "android" in code_parser_platforms, ( + "Expected platform 'android' extracted from publiccode.yaml " + f"with technique 'code_parser'. Found: {code_parser_platforms}" + ) + + code_repos = [entry["result"]["value"] for entry in metadata_result.results.get("code_repository", [])] + assert "https://example.com/italia/medusa.git" in code_repos + + app_domains = [entry["result"]["value"] for entry in metadata_result.results.get("application_domain", [])] + expected_domains = ["content-management", "office"] + for domain in expected_domains: + assert domain in app_domains + + requirements = metadata_result.results.get("requirements", []) + + req_map = {entry["result"]["name"]: entry["result"]["version"] for entry in requirements} + assert req_map["MySQL"] == ">=1.1,<1.3" + assert req_map["PostgreSQL"] == "3.2" + assert req_map["Oracle"] == ">=11.4" + assert req_map["IBM SoftLayer"] is None + assert req_map["NFC Reader"] is None + + version = metadata_result.results.get("version", []) + self.assertEqual(version[0]["result"]["value"], "1.0") + + descriptions = metadata_result.results.get("description", []) + self.assertTrue(len(descriptions) > 1, "Must be at least two descriptions found") + self.assertEqual(descriptions[0]["result"]["value"], 'This description can have a maximum 150 characters long. We should not fill the remaining space with "Lorem Ipsum". End') + + name = metadata_result.results.get("name", []) + self.assertEqual(name[0]["result"]["value"], "Medusa") + + keywords_values = metadata_result.results.get("keywords", []) + self.assertTrue(keywords_values) + keywords = keywords_values[0]["result"]["value"] + self.assertEqual(keywords[1],"Will run without a problem") + self.assertEqual(keywords[2],"Has zero bugs") + + development_status = metadata_result.results.get("development_status", []) + self.assertEqual(development_status[0]["result"]["value"], 'development') + + licenses = metadata_result.results.get("license", []) + print(licenses) + self.assertEqual(licenses[0]["result"]["spdx_id"], 'AGPL-3.0') + date_updated = metadata_result.results.get("date_updated", []) + self.assertEqual(date_updated[0]["result"]["value"], '2017-04-15') + + diff --git a/src/somef_core/test/test_python_parser.py b/src/somef_core/test/test_python_parser.py index 8c7d7ca..ffb768f 100644 --- a/src/somef_core/test/test_python_parser.py +++ b/src/somef_core/test/test_python_parser.py @@ -1,7 +1,7 @@ import unittest import os from pathlib import Path -from ..parser.python_parser import parse_pyproject_toml +# from ..parser.python_parser import parse_pyproject_toml from ..parser.python_parser import parse_requirements_txt from..parser.python_parser import parse_setup_py from ..process_results import Result @@ -11,48 +11,6 @@ test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep class TestPythonParser(unittest.TestCase): - - def test_parse_pyproject_toml(self): - pyproject_path = test_data_repositories + os.path.sep+ "gammalearn"+ os.path.sep+ "pyproject.toml" - result = Result() - - metadata_result = parse_pyproject_toml(pyproject_path, result, "https://example.org/pyproject.toml") - package_id = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) - # print(package_id) - self.assertTrue(len(package_id) > 0, "No identifier found") - self.assertEqual(package_id[0]["result"]["value"], "gammalearn") - - self.assertIn(constants.CAT_DESCRIPTION, result.results) - description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] - self.assertEqual(description, "A framework to easily train deep learning model on Imaging Atmospheric Cherenkov Telescopes data") - - self.assertIn(constants.CAT_AUTHORS, result.results) - authors = result.results[constants.CAT_AUTHORS] - self.assertEqual(len(authors), 2) - self.assertEqual(authors[0]["result"]["name"], "M. Jacquemont") - self.assertEqual(authors[0]["result"]["email"], "jacquemont@lapp.in2p3.fr") - self.assertEqual(authors[1]["result"]["name"], "T. Vuillaume") - self.assertEqual(authors[1]["result"]["email"], "thomas.vuillaume@lapp.in2p3.fr") - - self.assertIn(constants.CAT_LICENSE, result.results) - license_info = result.results[constants.CAT_LICENSE][0]["result"]["value"] - self.assertEqual(license_info, "License file: LICENSE") - - self.assertIn(constants.CAT_CODE_REPOSITORY, result.results) - repo_url = result.results[constants.CAT_CODE_REPOSITORY][0]["result"]["value"] - self.assertEqual(repo_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn") - - self.assertIn(constants.CAT_DOCUMENTATION, result.results) - doc_url = result.results[constants.CAT_DOCUMENTATION][0]["result"]["value"] - self.assertEqual(doc_url, "https://gammalearn.pages.in2p3.fr/gammalearn/") - - self.assertIn(constants.CAT_ISSUE_TRACKER, result.results) - issue_url = result.results[constants.CAT_ISSUE_TRACKER][0]["result"]["value"] - self.assertEqual(issue_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn/-/issues") - - self.assertIn(constants.CAT_REQUIREMENTS, result.results) - dependencies = result.results[constants.CAT_REQUIREMENTS] - self.assertEqual(len(dependencies), 25) def test_inspect4py_repository(self): """Test parsing of inspect4py repository files""" @@ -76,16 +34,7 @@ def test_inspect4py_repository(self): self.assertIn("astor", req_names) ####################### This is for testing pyroject.toml parsing ####################### - result = Result() - metadata_result = parse_pyproject_toml(pyproject_path, result, "https://example.org/pyproject.toml") - - self.assertIn(constants.CAT_REQUIREMENTS, result.results) - dependencies = result.results[constants.CAT_REQUIREMENTS] - self.assertEqual(len(dependencies), 11, "Incorrect number of requirements found in pyproject.toml") - - req_names = [req["result"]["name"] for req in dependencies] - self.assertIn("bs4", req_names) - self.assertIn("docstring_parser", req_names) + ####################### This is for testing setup.py parsing ####################### result = Result() @@ -103,23 +52,5 @@ def test_inspect4py_repository(self): programming_languages = result.results[constants.CAT_PROGRAMMING_LANGUAGES] self.assertEqual(programming_languages[0]["result"]["value"], "Python") - - def test_parse_pyproject_toml_requirements_version(self): - """Test parsing requirements with version and name. If version, must have name""" - pyproject_path = test_data_repositories + os.path.sep+ "sunpy"+ os.path.sep+ "pyproject.toml" - result = Result() - - metadata_result = parse_pyproject_toml(pyproject_path, result, "https://example.org/pyproject.toml") - - self.assertIn(constants.CAT_REQUIREMENTS, result.results) - dependencies = result.results[constants.CAT_REQUIREMENTS] - - for item in dependencies: - result = item.get("result", {}) - version = result.get("version", None) - name = result.get("name", None) - - self.assertTrue(version is None or name is not None, f"Error in requirement: {item}") - if __name__ == "__main__": unittest.main() \ No newline at end of file diff --git a/src/somef_core/test/test_regular_expressions.py b/src/somef_core/test/test_regular_expressions.py index 573ef9b..ea801af 100644 --- a/src/somef_core/test/test_regular_expressions.py +++ b/src/somef_core/test/test_regular_expressions.py @@ -48,7 +48,7 @@ def test_extract_dois(self): with open(test_data_path + "test_extract_dois.txt", "r") as data_file: test_text = data_file.read() c = regular_expressions.extract_doi_badges(test_text, Result(), test_data_path + "test_extract_dois.txt") - assert len(c.results[constants.CAT_IDENTIFIER]) == 2 + assert len(c.results[constants.CAT_IDENTIFIER]) == 3 def test_extract_binder_links(self): """Test designed to check if binder links are detected""" @@ -85,6 +85,17 @@ def test_extract_title_with_md(self): res = c.results[constants.CAT_FULL_TITLE][0] assert "SOMEF" == res[constants.PROP_RESULT][constants.PROP_VALUE] + def test_extract_title_ignored_header(self): + """Test that a header like 'Overview' and headers are not returned as full title""" + + with open(test_data_path + "README-EUVpy.md", "r") as data_file: + test_text = data_file.read() + c = regular_expressions.extract_title(test_text, Result(), + test_data_path + "README-EUVpy.md") + + assert constants.CAT_FULL_TITLE not in c.results or len(c.results[constants.CAT_FULL_TITLE]) == 0 + + def test_extract_readthedocs_1(self): """Test designed to check if readthedocs links are detected""" with open(test_data_path + "test_extract_readthedocs_1.txt", "r") as data_file: @@ -195,7 +206,6 @@ def test_issue_images(self): results = regular_expressions.extract_images(test_text, repo_url, None, Result(), test_data_path + "test_issue_images.txt", "main") img = results.results[constants.CAT_IMAGE] - print(img) assert len(img) == 2 #Test commented out because arxiv links with no context has demonstrated not to be useful @@ -213,7 +223,7 @@ def test_issue_181_2(self): result = regular_expressions.extract_arxiv_links(test_text, Result(), test_data_path + "test_issue_181_2.txt") arxiv_url = result.results[constants.CAT_RELATED_PAPERS][0]['result']['value'] expected_result = "https://arxiv.org/abs/2203.01044" - self.assertEquals(expected_result,arxiv_url) + self.assertEqual(expected_result,arxiv_url) def test_issue_181_3(self): """Test to test arxiv as embedded url, including same in bibtex""" with open(test_data_path + "test_issue_181_3.txt", "r") as data_file: @@ -222,7 +232,7 @@ def test_issue_181_3(self): test_data_path + "test_issue_181_3.txt") arxiv_url = result.results[constants.CAT_RELATED_PAPERS][0]['result']['value'] expected_result = "https://arxiv.org/abs/1907.11111" - self.assertEquals(expected_result, arxiv_url) + self.assertEqual(expected_result, arxiv_url) def test_issue_270(self): """Test designed to check if support channels are detected""" @@ -387,4 +397,109 @@ def test_issue_700(self): c = regular_expressions.extract_title(test_text, Result(), test_data_path + "README-ci-sample-project.md") - assert constants.CAT_FULL_TITLE not in c.results, "Category CAT_FULL_TITLE should be absent if there is no valid title." \ No newline at end of file + assert constants.CAT_FULL_TITLE not in c.results, "Category CAT_FULL_TITLE should be absent if there is no valid title." + + def test_issue_771(self): + """Test designed to check whether identifiers, package manager and documentation can be extracted + from badges in the readme file """ + with open(test_data_path + "README-sunpy.rst", "r") as data_file: + test_text = data_file.read() + identifiers = regular_expressions.extract_doi_badges(test_text, Result(), + test_data_path + "README-sunpy.rst") + documentation = regular_expressions.extract_readthedocs_badgeds(test_text, Result(), + test_data_path + "README-sunpy.rst") + package = regular_expressions.extract_package_distributions(test_text, Result(), + test_data_path + "README-sunpy.rst") + + # cant provide concrete doi or test will fail every time there is an update and we resolve the id + expected_doi = "https://doi.org/10.5281/zenodo." + doi_values = [] + if "identifier" in identifiers.results: + for result in identifiers.results["identifier"]: + if "result" in result and "value" in result["result"]: + doi_values.append(result["result"]["value"]) + assert expected_doi in doi_values[0], f"Expected DOI {expected_doi} not found in identifiers" + + expected_doc_url = "https://docs.sunpy.org/" + documentation_values = [] + if "documentation" in documentation.results: + for result in documentation.results["documentation"]: + if "result" in result and "value" in result["result"]: + documentation_values.append(result["result"]["value"]) + + assert expected_doc_url in documentation_values, f"Expected url documentation {expected_doc_url} not found in documentation" + + expected_packages = { + "https://pypi.org/project/sunpy/", + "https://anaconda.org/conda-forge/sunpy" + } + + package_distribution_values = [] + if "package_distribution" in package.results: + for result in package.results["package_distribution"]: + if "result" in result and "value" in result["result"]: + package_distribution_values.append(result["result"]["value"]) + + for expected in expected_packages: + assert expected in package_distribution_values, f"Package distribution {expected} not found in {package_distribution_values}" + + def test_issue_860(self): + """Test designed to check redthedocs links are extracted correctly when multiple links are present """ + documentation_values = [] + package_values = [] + + for readme_file in ["README-menty.md", "README-uncbiag.md"]: + with open(test_data_path + readme_file, "r") as data_file: + readme_text = data_file.read() + documentation = regular_expressions.extract_readthedocs_badgeds( + readme_text, Result(), test_data_path + readme_file + ) + if "documentation" in documentation.results: + for result in documentation.results["documentation"]: + if "result" in result and "value" in result["result"]: + # Solo agregamos strings + value = result["result"]["value"] + if isinstance(value, str): + documentation_values.append(value) + + if "package_distribution" in documentation.results: + for result in documentation.results["package_distribution"]: + value = result.get("result", {}).get("value") + if isinstance(value, str): + package_values.append(value) + + expected_doc_urls = { + "https://docs.mentpy.com/en/latest/?badge=latest", + "https://icon.readthedocs.io/en/master/" + } + + expected_package_urls = { + "https://pypi.org/project/mentpy" + } + + assert expected_doc_urls.issubset(set(documentation_values)), ( + f"Expected documentation URLs {expected_doc_urls} not found in {documentation_values}" + ) + assert expected_package_urls.issubset(set(package_values)), ( + f"Pypy package {expected_package_urls} not foun in package_distribution: {package_values}" + ) + + def test_readme_rst_readthedocs(self): + """Test designed to check whether rst readmes get stuck in extracting documentation """ + + with open(test_data_path + "README-sunpy.rst", "r") as data_file: + test_text = data_file.read() + + documentation = regular_expressions.extract_readthedocs_badgeds(test_text, Result(), + test_data_path + "README-sunpy.rst") + + + expected_doc_url = "https://docs.sunpy.org/" + documentation_values = [] + if "documentation" in documentation.results: + for result in documentation.results["documentation"]: + if "result" in result and "value" in result["result"]: + documentation_values.append(result["result"]["value"]) + + assert expected_doc_url in documentation_values, f"Expected url documentation {expected_doc_url} not found in documentation" + diff --git a/src/somef_core/test/test_software_type 2.py b/src/somef_core/test/test_software_type 2.py new file mode 100644 index 0000000..7a8bd9a --- /dev/null +++ b/src/somef_core/test/test_software_type 2.py @@ -0,0 +1,69 @@ +import unittest +import os +from pathlib import Path + +# from ..extract_software_type import check_ontologies, check_notebooks, check_command_line, check_extras, \ +# check_static_websites, check_workflow + +from ..extract_software_type import check_notebooks, check_command_line, check_extras, \ + check_static_websites, check_workflow + +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + + +class TestEXTRAS(unittest.TestCase): + """The following tests are made to check the workings of the classification + Each category has two tests with the format test_result-of-test_type + in order to identify what each of them does. + e.g: test_true_ontology runs the check_ontologies function on auroral-ontology-core which + is an ontology and returns true so the assert passes.""" + + # def test_true_ontology(self): + # path = test_data_repositories + "auroral-ontology-core" + # result = check_ontologies(path) + # assert result + + # def test_false_ontology(self): + # path = test_data_repositories + "sprint-main" + # result = check_ontologies(path) + # assert (result is False) + + def test_true_notebooks(self): + path = test_data_repositories + "basis_functions_approach_to_GP-master" + result = check_notebooks(path) + assert result + + def test_false_notebooks(self): + path = test_data_repositories + "ipynb-master" + result = check_notebooks(path) + assert (result is False) + + def test_true_commandline(self): + path = test_data_repositories + "Fermi" + result = check_command_line(path) + assert result + + def test_false_commandline(self): + path = test_data_repositories + "Clamp" + result = check_command_line(path) + assert (result is False) + + def test_true_extra(self): + path = test_data_repositories + "OWL-To-OAS-Specification-master" + result = check_extras(path) + assert result + + def test_false_extra(self): + path = test_data_repositories + "ipynb-master" + result = check_extras(path) + assert result is False + + def test_true_workflows(self): + path = test_data_repositories + "JAFFA-master" + result = check_workflow(path, 'JAFFA-master') + assert result + + def test_false_workflows(self): + path = test_data_repositories + "A-Dynamic-E-Commerce-Website-master" + result = check_workflow(path, 'DynamicPersonalWebsite-master') + assert result is False diff --git a/src/somef_core/test/test_software_type.py b/src/somef_core/test/test_software_type.py new file mode 100644 index 0000000..7a8bd9a --- /dev/null +++ b/src/somef_core/test/test_software_type.py @@ -0,0 +1,69 @@ +import unittest +import os +from pathlib import Path + +# from ..extract_software_type import check_ontologies, check_notebooks, check_command_line, check_extras, \ +# check_static_websites, check_workflow + +from ..extract_software_type import check_notebooks, check_command_line, check_extras, \ + check_static_websites, check_workflow + +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + + +class TestEXTRAS(unittest.TestCase): + """The following tests are made to check the workings of the classification + Each category has two tests with the format test_result-of-test_type + in order to identify what each of them does. + e.g: test_true_ontology runs the check_ontologies function on auroral-ontology-core which + is an ontology and returns true so the assert passes.""" + + # def test_true_ontology(self): + # path = test_data_repositories + "auroral-ontology-core" + # result = check_ontologies(path) + # assert result + + # def test_false_ontology(self): + # path = test_data_repositories + "sprint-main" + # result = check_ontologies(path) + # assert (result is False) + + def test_true_notebooks(self): + path = test_data_repositories + "basis_functions_approach_to_GP-master" + result = check_notebooks(path) + assert result + + def test_false_notebooks(self): + path = test_data_repositories + "ipynb-master" + result = check_notebooks(path) + assert (result is False) + + def test_true_commandline(self): + path = test_data_repositories + "Fermi" + result = check_command_line(path) + assert result + + def test_false_commandline(self): + path = test_data_repositories + "Clamp" + result = check_command_line(path) + assert (result is False) + + def test_true_extra(self): + path = test_data_repositories + "OWL-To-OAS-Specification-master" + result = check_extras(path) + assert result + + def test_false_extra(self): + path = test_data_repositories + "ipynb-master" + result = check_extras(path) + assert result is False + + def test_true_workflows(self): + path = test_data_repositories + "JAFFA-master" + result = check_workflow(path, 'JAFFA-master') + assert result + + def test_false_workflows(self): + path = test_data_repositories + "A-Dynamic-E-Commerce-Website-master" + result = check_workflow(path, 'DynamicPersonalWebsite-master') + assert result is False diff --git a/src/somef_core/test/test_toml_parser 2.py b/src/somef_core/test/test_toml_parser 2.py new file mode 100644 index 0000000..4e64953 --- /dev/null +++ b/src/somef_core/test/test_toml_parser 2.py @@ -0,0 +1,375 @@ +# -*- coding: utf-8 -*- +""" +Unified test suite for TOML parser. +Tests Cargo.toml, pyproject.toml, and Project.toml parsing. +""" + +import unittest +import os +from pathlib import Path + +from somef_core.process_results import Result +from somef_core.parser.toml_parser import parse_toml_file +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + + +class TestTomlParser(unittest.TestCase): + """Unified test class for all TOML file types""" + + def setUp(self): + """Set up test file paths""" + self.test_dir = os.path.dirname(os.path.abspath(__file__)) + + # Cargo.toml test file + self.cargo_toml_path = os.path.join( + self.test_dir, "test_data", "repositories", "rustdesk", "Cargo.toml" + ) + + # Project.toml test files (Julia) + self.pluto_project_path = os.path.join( + test_data_path, "Pluto.jl", "Project.toml" + ) + self.flux_project_path = os.path.join( + test_data_path, "Flux.jl", "Project.toml" + ) + + # pyproject.toml test files + self.gammalearn_pyproject_path = os.path.join( + test_data_path, "gammalearn", "pyproject.toml" + ) + self.inspect4py_pyproject_path = os.path.join( + test_data_path, "inspect4py", "pyproject.toml" + ) + self.sunpy_pyproject_path = os.path.join( + test_data_path, "sunpy", "pyproject.toml" + ) + + # ==================== Cargo.toml Tests ==================== + + def test_parse_cargo_toml(self): + """Test parsing Cargo.toml (Rust) file""" + self.assertTrue( + os.path.exists(self.cargo_toml_path), + f"Test file not found: {self.cargo_toml_path}" + ) + + result = Result() + # parse_toml_file(self.cargo_toml_path, result, "test") + print("self.cargo_toml_path:", self.cargo_toml_path) + # parse_toml_file(self.cargo_toml_path, result, "http://example.com/rustdesk/Cargo.toml") + parse_toml_file(self.cargo_toml_path, result, self.cargo_toml_path) + + self.assertIn(constants.CAT_HAS_PACKAGE_FILE, result.results) + package_file = result.results[constants.CAT_HAS_PACKAGE_FILE][0]["result"]["value"] + + # self.assertEqual(package_file, "Cargo.toml") + self.assertEqual(package_file, self.cargo_toml_path) + + self.assertIn(constants.CAT_PACKAGE_ID, result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "rustdesk") + + self.assertIn(constants.CAT_VERSION, result.results) + version = result.results[constants.CAT_VERSION][0]["result"]["value"] + self.assertEqual(version, "1.4.0") + + self.assertIn(constants.CAT_DESCRIPTION, result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "RustDesk Remote Desktop") + + self.assertIn(constants.CAT_AUTHORS, result.results) + authors = result.results[constants.CAT_AUTHORS] + self.assertEqual(len(authors), 1) + self.assertEqual(authors[0]["result"]["name"], "rustdesk") + self.assertEqual(authors[0]["result"]["email"], "info@rustdesk.com") + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + dep_names = [d["result"]["name"] for d in dependencies] + self.assertIn("async-trait", dep_names) + self.assertIn("serde", dep_names) + self.assertIn("lazy_static", dep_names) + + # ==================== Project.toml (Julia) Tests ==================== + + def test_parse_pluto_project_toml(self): + """Test parsing Pluto's Project.toml (Julia) file""" + result = Result() + + # metadata_result = parse_toml_file( + # self.pluto_project_path, + # result, + # "http://example.com/repo1/Project.toml" + # ) + + metadata_result = parse_toml_file( + self.pluto_project_path, + result, + self.pluto_project_path + ) + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "Project.toml") + self.assertEqual(package_results[0]["result"]["value"], self.pluto_project_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + self.assertEqual(package_results[0]["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id_results) > 0, "No package ID found") + self.assertEqual(package_id_results[0]["result"]["value"], "Pluto") + self.assertEqual(package_id_results[0]["result"]["type"], constants.STRING) + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertTrue(len(version_results) > 0, "No version found") + self.assertEqual(version_results[0]["result"]["value"], "0.20.20") + self.assertEqual(version_results[0]["result"]["type"], constants.STRING) + + identifier_results = metadata_result.results.get(constants.CAT_IDENTIFIER, []) + self.assertTrue(len(identifier_results) > 0, "No identifier found") + self.assertEqual( + identifier_results[0]["result"]["value"], + "c3e4b0f8-55cb-11ea-2926-15256bba5781" + ) + self.assertEqual(identifier_results[0]["result"]["type"], constants.STRING) + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(author_results) > 0, "No author found") + self.assertEqual(author_results[0]["result"]["name"], "Fons van der Plas") + self.assertEqual(author_results[0]["result"]["email"], "fons@plutojl.org") + self.assertEqual(author_results[0]["result"]["type"], constants.AGENT) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + dep_values = [req["result"]["value"] for req in requirements_results] + self.assertIn("HTTP", dep_values) + self.assertIn("Markdown", dep_values) + self.assertIn("Pkg", dep_values) + self.assertIn("REPL", dep_values) + + for req in requirements_results: + self.assertEqual(req["result"]["type"], constants.STRING) + self.assertEqual(req["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertTrue(len(runtime_results) > 0, "No runtime platform info found") + + runtime_dict = {r["result"]["package"]: r["result"]["version"] for r in runtime_results} + self.assertIn("HTTP", runtime_dict) + self.assertEqual(runtime_dict["HTTP"], "^1.10.17") + self.assertIn("julia", runtime_dict) + self.assertEqual(runtime_dict["julia"], "^1.10") + + for runtime in runtime_results: + self.assertEqual(runtime["result"]["type"], constants.STRING) + self.assertEqual(runtime["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + def test_parse_flux_project_toml(self): + """Test parsing Flux's Project.toml (Julia) file""" + result = Result() + + # metadata_result = parse_toml_file( + # self.flux_project_path, + # result, + # "http://example.com/repo2/Project.toml" + # ) + metadata_result = parse_toml_file( + self.flux_project_path, + result, + self.flux_project_path + ) + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "Project.toml") + self.assertEqual(package_results[0]["result"]["value"], self.flux_project_path) + + package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id_results) > 0, "No package ID found") + self.assertEqual(package_id_results[0]["result"]["value"], "Flux") + self.assertEqual(package_id_results[0]["result"]["type"], constants.STRING) + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertTrue(len(version_results) > 0, "No version found") + self.assertEqual(version_results[0]["result"]["value"], "0.16.5") + self.assertEqual(version_results[0]["result"]["type"], constants.STRING) + + identifier_results = metadata_result.results.get(constants.CAT_IDENTIFIER, []) + self.assertTrue(len(identifier_results) > 0, "No identifier found") + self.assertEqual( + identifier_results[0]["result"]["value"], + "587475ba-b771-5e3f-ad9e-33799f191a9c" + ) + self.assertEqual(identifier_results[0]["result"]["type"], constants.STRING) + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertEqual(len(author_results), 0, "No authors should be found in Flux's Project.toml") + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + dep_values = [req["result"]["value"] for req in requirements_results] + self.assertIn("Zygote", dep_values) + self.assertIn("NNlib", dep_values) + self.assertIn("Optimisers", dep_values) + self.assertIn("LinearAlgebra", dep_values) + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertTrue(len(runtime_results) > 0, "No runtime platform info found") + + runtime_dict = {r["result"]["package"]: r["result"]["version"] for r in runtime_results} + self.assertIn("julia", runtime_dict) + self.assertEqual(runtime_dict["julia"], "1.10") + self.assertIn("NNlib", runtime_dict) + self.assertEqual(runtime_dict["NNlib"], "0.9.22") + self.assertIn("Zygote", runtime_dict) + self.assertEqual(runtime_dict["Zygote"], "0.6.67, 0.7") + + # ==================== pyproject.toml Tests ==================== + + def test_parse_gammalearn_pyproject_toml(self): + """Test parsing gammalearn's pyproject.toml file""" + result = Result() + + metadata_result = parse_toml_file( + self.gammalearn_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + package_id = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id) > 0, "No identifier found") + self.assertEqual(package_id[0]["result"]["value"], "gammalearn") + + self.assertIn(constants.CAT_DESCRIPTION, result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual( + description, + "A framework to easily train deep learning model on Imaging Atmospheric Cherenkov Telescopes data" + ) + + self.assertIn(constants.CAT_AUTHORS, result.results) + authors = result.results[constants.CAT_AUTHORS] + self.assertEqual(len(authors), 2) + self.assertEqual(authors[0]["result"]["name"], "M. Jacquemont") + self.assertEqual(authors[0]["result"]["email"], "jacquemont@lapp.in2p3.fr") + self.assertEqual(authors[1]["result"]["name"], "T. Vuillaume") + self.assertEqual(authors[1]["result"]["email"], "thomas.vuillaume@lapp.in2p3.fr") + + self.assertIn(constants.CAT_LICENSE, result.results) + license_info = result.results[constants.CAT_LICENSE][0]["result"]["value"] + self.assertEqual(license_info, "License file: LICENSE") + + self.assertIn(constants.CAT_CODE_REPOSITORY, result.results) + repo_url = result.results[constants.CAT_CODE_REPOSITORY][0]["result"]["value"] + self.assertEqual(repo_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn") + + self.assertIn(constants.CAT_DOCUMENTATION, result.results) + doc_url = result.results[constants.CAT_DOCUMENTATION][0]["result"]["value"] + self.assertEqual(doc_url, "https://gammalearn.pages.in2p3.fr/gammalearn/") + + self.assertIn(constants.CAT_ISSUE_TRACKER, result.results) + issue_url = result.results[constants.CAT_ISSUE_TRACKER][0]["result"]["value"] + self.assertEqual(issue_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn/-/issues") + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual(len(dependencies), 25) + + def test_parse_inspect4py_pyproject_toml(self): + """Test parsing inspect4py's pyproject.toml file""" + result = Result() + + metadata_result = parse_toml_file( + self.inspect4py_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual( + len(dependencies), + 11, + "Incorrect number of requirements found in pyproject.toml" + ) + + req_names = [req["result"]["name"] for req in dependencies] + self.assertIn("bs4", req_names) + self.assertIn("docstring_parser", req_names) + + def test_parse_sunpy_pyproject_toml_requirements_version(self): + """Test parsing requirements with version and name from sunpy's pyproject.toml""" + result = Result() + + metadata_result = parse_toml_file( + self.sunpy_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + for item in dependencies: + result_data = item.get("result", {}) + version = result_data.get("version", None) + name = result_data.get("name", None) + + self.assertTrue( + version is None or name is not None, + f"Error in requirement: {item}" + ) + + def test_parse_sunpy_pyproject_toml_issue_769(self): + """Test parsing requirements with brackets (issue #769) from sunpy's pyproject.toml""" + result = Result() + + metadata_result = parse_toml_file( + self.sunpy_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + self.assertTrue( + any( + item.get("result", {}).get("name") == "setuptools_scm[toml]" + and item.get("result", {}).get("version") == ">=8.0.1" + for item in dependencies + ), + "Expected dependency 'setuptools_scm[toml]' with version '>=8.0.1' not found." + ) + + def test_common_fields_across_formats(self): + """Test that common fields (name, version, authors) work consistently across all formats""" + + # Test Cargo.toml + cargo_result = Result() + parse_toml_file(self.cargo_toml_path, cargo_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, cargo_result.results) + self.assertIn(constants.CAT_VERSION, cargo_result.results) + self.assertIn(constants.CAT_AUTHORS, cargo_result.results) + + # Test Project.toml + julia_result = Result() + parse_toml_file(self.pluto_project_path, julia_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, julia_result.results) + self.assertIn(constants.CAT_VERSION, julia_result.results) + self.assertIn(constants.CAT_AUTHORS, julia_result.results) + + # Test pyproject.toml + python_result = Result() + parse_toml_file(self.gammalearn_pyproject_path, python_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, python_result.results) + self.assertIn(constants.CAT_AUTHORS, python_result.results) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/somef_core/test/test_toml_parser.py b/src/somef_core/test/test_toml_parser.py new file mode 100644 index 0000000..4e64953 --- /dev/null +++ b/src/somef_core/test/test_toml_parser.py @@ -0,0 +1,375 @@ +# -*- coding: utf-8 -*- +""" +Unified test suite for TOML parser. +Tests Cargo.toml, pyproject.toml, and Project.toml parsing. +""" + +import unittest +import os +from pathlib import Path + +from somef_core.process_results import Result +from somef_core.parser.toml_parser import parse_toml_file +from somef_core.utils import constants + +test_data_path = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep + + +class TestTomlParser(unittest.TestCase): + """Unified test class for all TOML file types""" + + def setUp(self): + """Set up test file paths""" + self.test_dir = os.path.dirname(os.path.abspath(__file__)) + + # Cargo.toml test file + self.cargo_toml_path = os.path.join( + self.test_dir, "test_data", "repositories", "rustdesk", "Cargo.toml" + ) + + # Project.toml test files (Julia) + self.pluto_project_path = os.path.join( + test_data_path, "Pluto.jl", "Project.toml" + ) + self.flux_project_path = os.path.join( + test_data_path, "Flux.jl", "Project.toml" + ) + + # pyproject.toml test files + self.gammalearn_pyproject_path = os.path.join( + test_data_path, "gammalearn", "pyproject.toml" + ) + self.inspect4py_pyproject_path = os.path.join( + test_data_path, "inspect4py", "pyproject.toml" + ) + self.sunpy_pyproject_path = os.path.join( + test_data_path, "sunpy", "pyproject.toml" + ) + + # ==================== Cargo.toml Tests ==================== + + def test_parse_cargo_toml(self): + """Test parsing Cargo.toml (Rust) file""" + self.assertTrue( + os.path.exists(self.cargo_toml_path), + f"Test file not found: {self.cargo_toml_path}" + ) + + result = Result() + # parse_toml_file(self.cargo_toml_path, result, "test") + print("self.cargo_toml_path:", self.cargo_toml_path) + # parse_toml_file(self.cargo_toml_path, result, "http://example.com/rustdesk/Cargo.toml") + parse_toml_file(self.cargo_toml_path, result, self.cargo_toml_path) + + self.assertIn(constants.CAT_HAS_PACKAGE_FILE, result.results) + package_file = result.results[constants.CAT_HAS_PACKAGE_FILE][0]["result"]["value"] + + # self.assertEqual(package_file, "Cargo.toml") + self.assertEqual(package_file, self.cargo_toml_path) + + self.assertIn(constants.CAT_PACKAGE_ID, result.results) + package_id = result.results[constants.CAT_PACKAGE_ID][0]["result"]["value"] + self.assertEqual(package_id, "rustdesk") + + self.assertIn(constants.CAT_VERSION, result.results) + version = result.results[constants.CAT_VERSION][0]["result"]["value"] + self.assertEqual(version, "1.4.0") + + self.assertIn(constants.CAT_DESCRIPTION, result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual(description, "RustDesk Remote Desktop") + + self.assertIn(constants.CAT_AUTHORS, result.results) + authors = result.results[constants.CAT_AUTHORS] + self.assertEqual(len(authors), 1) + self.assertEqual(authors[0]["result"]["name"], "rustdesk") + self.assertEqual(authors[0]["result"]["email"], "info@rustdesk.com") + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + dep_names = [d["result"]["name"] for d in dependencies] + self.assertIn("async-trait", dep_names) + self.assertIn("serde", dep_names) + self.assertIn("lazy_static", dep_names) + + # ==================== Project.toml (Julia) Tests ==================== + + def test_parse_pluto_project_toml(self): + """Test parsing Pluto's Project.toml (Julia) file""" + result = Result() + + # metadata_result = parse_toml_file( + # self.pluto_project_path, + # result, + # "http://example.com/repo1/Project.toml" + # ) + + metadata_result = parse_toml_file( + self.pluto_project_path, + result, + self.pluto_project_path + ) + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "Project.toml") + self.assertEqual(package_results[0]["result"]["value"], self.pluto_project_path) + self.assertEqual(package_results[0]["result"]["type"], constants.URL) + self.assertEqual(package_results[0]["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id_results) > 0, "No package ID found") + self.assertEqual(package_id_results[0]["result"]["value"], "Pluto") + self.assertEqual(package_id_results[0]["result"]["type"], constants.STRING) + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertTrue(len(version_results) > 0, "No version found") + self.assertEqual(version_results[0]["result"]["value"], "0.20.20") + self.assertEqual(version_results[0]["result"]["type"], constants.STRING) + + identifier_results = metadata_result.results.get(constants.CAT_IDENTIFIER, []) + self.assertTrue(len(identifier_results) > 0, "No identifier found") + self.assertEqual( + identifier_results[0]["result"]["value"], + "c3e4b0f8-55cb-11ea-2926-15256bba5781" + ) + self.assertEqual(identifier_results[0]["result"]["type"], constants.STRING) + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertTrue(len(author_results) > 0, "No author found") + self.assertEqual(author_results[0]["result"]["name"], "Fons van der Plas") + self.assertEqual(author_results[0]["result"]["email"], "fons@plutojl.org") + self.assertEqual(author_results[0]["result"]["type"], constants.AGENT) + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + dep_values = [req["result"]["value"] for req in requirements_results] + self.assertIn("HTTP", dep_values) + self.assertIn("Markdown", dep_values) + self.assertIn("Pkg", dep_values) + self.assertIn("REPL", dep_values) + + for req in requirements_results: + self.assertEqual(req["result"]["type"], constants.STRING) + self.assertEqual(req["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertTrue(len(runtime_results) > 0, "No runtime platform info found") + + runtime_dict = {r["result"]["package"]: r["result"]["version"] for r in runtime_results} + self.assertIn("HTTP", runtime_dict) + self.assertEqual(runtime_dict["HTTP"], "^1.10.17") + self.assertIn("julia", runtime_dict) + self.assertEqual(runtime_dict["julia"], "^1.10") + + for runtime in runtime_results: + self.assertEqual(runtime["result"]["type"], constants.STRING) + self.assertEqual(runtime["technique"], constants.TECHNIQUE_CODE_CONFIG_PARSER) + + def test_parse_flux_project_toml(self): + """Test parsing Flux's Project.toml (Julia) file""" + result = Result() + + # metadata_result = parse_toml_file( + # self.flux_project_path, + # result, + # "http://example.com/repo2/Project.toml" + # ) + metadata_result = parse_toml_file( + self.flux_project_path, + result, + self.flux_project_path + ) + + package_results = metadata_result.results.get(constants.CAT_HAS_PACKAGE_FILE, []) + self.assertTrue(len(package_results) > 0, "No package file info found") + # self.assertEqual(package_results[0]["result"]["value"], "Project.toml") + self.assertEqual(package_results[0]["result"]["value"], self.flux_project_path) + + package_id_results = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id_results) > 0, "No package ID found") + self.assertEqual(package_id_results[0]["result"]["value"], "Flux") + self.assertEqual(package_id_results[0]["result"]["type"], constants.STRING) + + version_results = metadata_result.results.get(constants.CAT_VERSION, []) + self.assertTrue(len(version_results) > 0, "No version found") + self.assertEqual(version_results[0]["result"]["value"], "0.16.5") + self.assertEqual(version_results[0]["result"]["type"], constants.STRING) + + identifier_results = metadata_result.results.get(constants.CAT_IDENTIFIER, []) + self.assertTrue(len(identifier_results) > 0, "No identifier found") + self.assertEqual( + identifier_results[0]["result"]["value"], + "587475ba-b771-5e3f-ad9e-33799f191a9c" + ) + self.assertEqual(identifier_results[0]["result"]["type"], constants.STRING) + + author_results = metadata_result.results.get(constants.CAT_AUTHORS, []) + self.assertEqual(len(author_results), 0, "No authors should be found in Flux's Project.toml") + + requirements_results = metadata_result.results.get(constants.CAT_REQUIREMENTS, []) + self.assertTrue(len(requirements_results) > 0, "No dependencies found") + + dep_values = [req["result"]["value"] for req in requirements_results] + self.assertIn("Zygote", dep_values) + self.assertIn("NNlib", dep_values) + self.assertIn("Optimisers", dep_values) + self.assertIn("LinearAlgebra", dep_values) + + runtime_results = metadata_result.results.get(constants.CAT_RUNTIME_PLATFORM, []) + self.assertTrue(len(runtime_results) > 0, "No runtime platform info found") + + runtime_dict = {r["result"]["package"]: r["result"]["version"] for r in runtime_results} + self.assertIn("julia", runtime_dict) + self.assertEqual(runtime_dict["julia"], "1.10") + self.assertIn("NNlib", runtime_dict) + self.assertEqual(runtime_dict["NNlib"], "0.9.22") + self.assertIn("Zygote", runtime_dict) + self.assertEqual(runtime_dict["Zygote"], "0.6.67, 0.7") + + # ==================== pyproject.toml Tests ==================== + + def test_parse_gammalearn_pyproject_toml(self): + """Test parsing gammalearn's pyproject.toml file""" + result = Result() + + metadata_result = parse_toml_file( + self.gammalearn_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + package_id = metadata_result.results.get(constants.CAT_PACKAGE_ID, []) + self.assertTrue(len(package_id) > 0, "No identifier found") + self.assertEqual(package_id[0]["result"]["value"], "gammalearn") + + self.assertIn(constants.CAT_DESCRIPTION, result.results) + description = result.results[constants.CAT_DESCRIPTION][0]["result"]["value"] + self.assertEqual( + description, + "A framework to easily train deep learning model on Imaging Atmospheric Cherenkov Telescopes data" + ) + + self.assertIn(constants.CAT_AUTHORS, result.results) + authors = result.results[constants.CAT_AUTHORS] + self.assertEqual(len(authors), 2) + self.assertEqual(authors[0]["result"]["name"], "M. Jacquemont") + self.assertEqual(authors[0]["result"]["email"], "jacquemont@lapp.in2p3.fr") + self.assertEqual(authors[1]["result"]["name"], "T. Vuillaume") + self.assertEqual(authors[1]["result"]["email"], "thomas.vuillaume@lapp.in2p3.fr") + + self.assertIn(constants.CAT_LICENSE, result.results) + license_info = result.results[constants.CAT_LICENSE][0]["result"]["value"] + self.assertEqual(license_info, "License file: LICENSE") + + self.assertIn(constants.CAT_CODE_REPOSITORY, result.results) + repo_url = result.results[constants.CAT_CODE_REPOSITORY][0]["result"]["value"] + self.assertEqual(repo_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn") + + self.assertIn(constants.CAT_DOCUMENTATION, result.results) + doc_url = result.results[constants.CAT_DOCUMENTATION][0]["result"]["value"] + self.assertEqual(doc_url, "https://gammalearn.pages.in2p3.fr/gammalearn/") + + self.assertIn(constants.CAT_ISSUE_TRACKER, result.results) + issue_url = result.results[constants.CAT_ISSUE_TRACKER][0]["result"]["value"] + self.assertEqual(issue_url, "https://gitlab.in2p3.fr/gammalearn/gammalearn/-/issues") + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual(len(dependencies), 25) + + def test_parse_inspect4py_pyproject_toml(self): + """Test parsing inspect4py's pyproject.toml file""" + result = Result() + + metadata_result = parse_toml_file( + self.inspect4py_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + self.assertEqual( + len(dependencies), + 11, + "Incorrect number of requirements found in pyproject.toml" + ) + + req_names = [req["result"]["name"] for req in dependencies] + self.assertIn("bs4", req_names) + self.assertIn("docstring_parser", req_names) + + def test_parse_sunpy_pyproject_toml_requirements_version(self): + """Test parsing requirements with version and name from sunpy's pyproject.toml""" + result = Result() + + metadata_result = parse_toml_file( + self.sunpy_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + for item in dependencies: + result_data = item.get("result", {}) + version = result_data.get("version", None) + name = result_data.get("name", None) + + self.assertTrue( + version is None or name is not None, + f"Error in requirement: {item}" + ) + + def test_parse_sunpy_pyproject_toml_issue_769(self): + """Test parsing requirements with brackets (issue #769) from sunpy's pyproject.toml""" + result = Result() + + metadata_result = parse_toml_file( + self.sunpy_pyproject_path, + result, + "https://example.org/pyproject.toml" + ) + + self.assertIn(constants.CAT_REQUIREMENTS, result.results) + dependencies = result.results[constants.CAT_REQUIREMENTS] + + self.assertTrue( + any( + item.get("result", {}).get("name") == "setuptools_scm[toml]" + and item.get("result", {}).get("version") == ">=8.0.1" + for item in dependencies + ), + "Expected dependency 'setuptools_scm[toml]' with version '>=8.0.1' not found." + ) + + def test_common_fields_across_formats(self): + """Test that common fields (name, version, authors) work consistently across all formats""" + + # Test Cargo.toml + cargo_result = Result() + parse_toml_file(self.cargo_toml_path, cargo_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, cargo_result.results) + self.assertIn(constants.CAT_VERSION, cargo_result.results) + self.assertIn(constants.CAT_AUTHORS, cargo_result.results) + + # Test Project.toml + julia_result = Result() + parse_toml_file(self.pluto_project_path, julia_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, julia_result.results) + self.assertIn(constants.CAT_VERSION, julia_result.results) + self.assertIn(constants.CAT_AUTHORS, julia_result.results) + + # Test pyproject.toml + python_result = Result() + parse_toml_file(self.gammalearn_pyproject_path, python_result, "test") + self.assertIn(constants.CAT_PACKAGE_ID, python_result.results) + self.assertIn(constants.CAT_AUTHORS, python_result.results) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/somef_core/test/test_wiki.py b/src/somef_core/test/test_wiki.py index 375651b..9818d00 100644 --- a/src/somef_core/test/test_wiki.py +++ b/src/somef_core/test/test_wiki.py @@ -5,7 +5,7 @@ from .. import somef_cli test_data_path = str(Path(__file__).parent / "test_data") + os.path.sep - +test_data_repositories = str(Path(__file__).parent / "test_data" / "repositories") + os.path.sep class TestWiki(unittest.TestCase): # def test_no_wiki(self): # """Checks if codemeta file has been exported without wiki""" @@ -42,7 +42,9 @@ def test_wiki_without_content(self): """Checks if codemeta file has been exported with wiki content""" somef_cli.run_cli(threshold=0.8, ignore_classifiers=False, - repo_url='https://github.com/dgarijo/Widoco', + # repo_url='https://github.com/dgarijo/Widoco', + repo_url=None, + local_repo= test_data_repositories + "Widoco", doc_src=None, in_file=None, output=None, diff --git a/src/somef_core/utils/constants.py b/src/somef_core/utils/constants.py index e8ebd97..1829bc8 100644 --- a/src/somef_core/utils/constants.py +++ b/src/somef_core/utils/constants.py @@ -24,7 +24,9 @@ REGEXP_PYPI_2 = "[![Latest PyPI version]" REGEXP_COLAB = "https://colab.research.google.com/drive" # needed to cleanup bibtext files. -REGEXP_BIBTEX = r'\@[a-zA-Z]+\{[.\n\S\s]+?[author|title][.\n\S\s]+?[author|title][.\n\S\s]+?\n\}' +# REGEXP_BIBTEX = r'\@[a-zA-Z]+\{[.\n\S\s]+?[author|title][.\n\S\s]+?[author|title][.\n\S\s]+?\n\}' +# REGEXP_BIBTEX = r'@[a-zA-Z]+\{[\s\S]*?(?:author|title)[\s\S]*?(?:author|title)[\s\S]*?\}' +REGEXP_BIBTEX = r'@[a-zA-Z]+\{(?=[\s\S]*\bauthor\b)(?=[\s\S]*\btitle\b)[\s\S]*?\}' REGEXP_DOI = r'\[\!\[DOI\]([^\]]+)\]\(([^)]+)\)' REGEXP_LINKS = r"\[(.*?)?\]\(([^)]+)\)" REGEXP_IMAGES = r"!\[(.*?)?\]\((.*?)?\)" @@ -33,6 +35,48 @@ REGEXP_MONTH = r'month\s*=\s*{(\d{1,2})}' REGEXP_PAGES = r'pages\s*=\s*{([\d-]+)}' +# Project Homepage badge' +REGEXP_PROJECT_HOMEPAGE = r'\[\!\[Project homepage\]([^\]]+)\]\(([^)]+)\)' + +# Redthedocs badges' +# REGEXP_READTHEDOCS_BADGES = r"https?://[^\s]*readthedocs\.org/projects/[^\s]*/badge/\?version=[^\s]*(?:.|\n)*?:target:\s*(https?://[^\s]+)" +# REGEXP_READTHEDOCS_BADGES = r"https?://readthedocs\.org/projects/[^/\s]+/badge/\?version=[^)\s]+" +# REGEXP_READTHEDOCS_BADGES = ( +# r"https?://readthedocs\.org/projects/[^/\s]+/badge/\?version=[^)\s]+" +# r"(?:.|\n)*?:target:\s*(https?://[^\s]+)" # rst +# r"|" +# r"\((https?://readthedocs\.org/projects/[^/\s]+/[^)\s]+)\)" # md +# ) +REGEXP_READTHEDOCS_RST = ( + r"https?://readthedocs\.org/projects/[^\s/]+/badge/[^\s]*" + r"[^\n]*?:target:\s*(https?://[^\s\"']+)" +) +REGEXP_READTHEDOCS_MD = ( + r"\(\s*(https?://[^\s\)]+\.readthedocs\.io[^\s\)]*)\s*\)" +) + +# REGEXP_READTHEDOCS_HTML = ( +# r"]+?href=['\"](https?://[^'\"\s]+?)['\"][^>]*?>" +# r"(?:(?!)[\s\S])*?" +# r"]+?src=['\"]https?://(?:readthedocs\.org/projects/|img\.shields\.io/pypi/)[^'\"\s]*" +# ) + +REGEXP_READTHEDOCS_HTML = (r""" + ]*\bhref=['"](https?://[^'"\s]+)['"] + [^>]*> + (?: + [^<]+ + | + <(?!/a\b)[^>]*> + )* + ]*\bsrc=['"] + https?://(?:readthedocs\.org/projects/|img\.shields\.io/pypi/) + [^'"\s>]+ + ['"] + """ +) # For natural language citation REGEXP_DOI_NATURAL = r'10\.\d{4,9}/[-._;()/:A-Za-z0-9]+' REGEXP_YEAR_NATURAL = r'\b(19|20)\d{2}\b' @@ -41,7 +85,8 @@ REGEXP_TITLE_NATURAL = r'["“](.+?)["”]' #License spdx -REGEXP_APACHE = r'(?i)apache\s+license\s*,?\s*version\s*2\.0' +# REGEXP_APACHE = r'(?i)apache\s+license\s*,?\s*version\s*2\.0' +REGEXP_APACHE = r'(?i)apache(?:\s+license)?\s*(?:,?\s*version\s*)?2\.0' REGEXP_GPL3 = r'(?i)gnu\s+general\s+public\s+license\s*,?\s*version\s*3\.0' REGEXP_MIT = r'(?i)mit\s+license' REGEXP_BSD2 = r'(?i)(bsd\s*-?\s*2-?clause(?:\s*license)?|redistribution\s+and\s+use\s+in\s+source\s+and\s+binary\s+forms)' @@ -55,6 +100,17 @@ REGEXP_MPL2 = r'(?i)mozilla\s+public\s+license\s*,?\s*version\s*2\.0' REGEXP_UNLICENSE = r'(?i)the\s+unlicense' +# Detect organization in authors.md +REGEXP_LTD_INC = r'\b(inc|ltd|llc|corporation)([.,]|\b)' + +# Detect duplicate all kind of dois. +REGEXP_ALL_DOIS = r'10\.\d{4,9}/[-._;()/:A-Z0-9]+' + +# Detect zenodo latest doi in readme. +REGEXP_ZENODO_LATEST_DOI = r':target:\s*(https://zenodo\.org/badge/latestdoi/\d+)' +REGEXP_ZENODO_DOI = r'https://zenodo\.org/badge/DOI/\d+' +REGEXP_ZENODO_JSON_LD = r"]*type=['\"]application/ld\+json['\"][^>]*>(.*?)" + LICENSES_DICT = { "Apache License 2.0": {"regex": REGEXP_APACHE, "spdx_id": "Apache-2.0"}, "GNU General Public License v3.0": {"regex": REGEXP_GPL3, "spdx_id": "GPL-3.0"}, @@ -83,6 +139,7 @@ CAT_CONTACT = "contact" CAT_DATE_CREATED = "date_created" CAT_DATE_UPDATED = "date_updated" +CAT_DATE_PUBLISHED = "date_published" CAT_DESCRIPTION = "description" CAT_DOCUMENTATION = "documentation" CAT_DOWNLOAD = "download" @@ -93,6 +150,7 @@ CAT_FORKS_URLS = "forks_url" CAT_FULL_NAME = "full_name" CAT_FULL_TITLE = "full_title" +CAT_HOMEPAGE = "homepage" CAT_HAS_BUILD_FILE = "has_build_file" CAT_HAS_SCRIPT_FILE = "has_script_file" CAT_IDENTIFIER = "identifier" @@ -107,14 +165,25 @@ CAT_ONTOLOGIES = "ontologies" CAT_OWNER = "owner" CAT_PACKAGE_DISTRIBUTION = "package_distribution" +REGEXP_PACKAGE_MANAGER = r""" + (?P + https?:// + (?: + (?:pypi\.python\.org/pypi/[^/\s]+)| + (?:anaconda\.org/[^/\s]+/[^/\s]+)| + (?:search\.maven\.org/artifact/[^/\s]+/[^/\s]+(?:/[^/\s]+)?) + ) + ) +""" CAT_PROGRAMMING_LANGUAGES = "programming_languages" CAT_README_URL = "readme_url" CAT_RELATED_DOCUMENTATION = "related_documentation" CAT_RELATED_PAPERS = "related_papers" CAT_RELEASES = "releases" +CAT_REQUIREMENTS = "requirements" CAT_RUN = "run" +CAT_RUNTIME_PLATFORM = "runtime_platform" CAT_STATUS = "repository_status" -CAT_REQUIREMENTS = "requirements" CAT_STARS = "stargazers_count" CAT_SUPPORT = "support" CAT_SUPPORT_CHANNELS = "support_channels" @@ -125,10 +194,10 @@ CAT_HAS_PACKAGE_FILE = "has_package_file" CAT_VERSION = "version" CAT_CONTINUOUS_INTEGRATION= "continuous_integration" - +CAT_FUNDING = "funding" +CAT_DEV_STATUS = "development_status" # Special category: missing categories CAT_MISSING = "somef_missing_categories" - # list of those categories to be analyzed with supervised classification. # supervised_categories = [CAT_DESCRIPTION, CAT_CITATION, CAT_INSTALLATION, CAT_INVOCATION] # update jan 2025: only description is run, since the installation classifier is a bit noisy. @@ -142,9 +211,9 @@ CAT_DOCUMENTATION, CAT_DOWNLOAD, CAT_DOWNLOAD_URL, CAT_EXECUTABLE_EXAMPLE, CAT_FAQ, CAT_FORK_COUNTS, CAT_FORKS_URLS, CAT_FULL_NAME, CAT_FULL_TITLE, CAT_HAS_BUILD_FILE, CAT_HAS_SCRIPT_FILE, CAT_IDENTIFIER, CAT_IMAGE, CAT_INSTALLATION, - CAT_INVOCATION, CAT_ISSUE_TRACKER, CAT_KEYWORDS, CAT_LICENSE, CAT_LOGO, CAT_NAME, CAT_ONTOLOGIES, + CAT_INVOCATION, CAT_ISSUE_TRACKER,CAT_HOMEPAGE, CAT_KEYWORDS, CAT_LICENSE, CAT_LOGO, CAT_NAME, CAT_ONTOLOGIES, CAT_OWNER, CAT_PACKAGE_DISTRIBUTION, CAT_HAS_PACKAGE_FILE, CAT_PROGRAMMING_LANGUAGES, CAT_README_URL, - CAT_RELATED_DOCUMENTATION, CAT_RELEASES, CAT_RUN, CAT_RELATED_PAPERS, + CAT_RELATED_DOCUMENTATION, CAT_RELEASES, CAT_RUN, CAT_RUNTIME_PLATFORM, CAT_RELATED_PAPERS, CAT_STATUS, CAT_REQUIREMENTS, CAT_STARS, CAT_SUPPORT, CAT_SUPPORT_CHANNELS, CAT_USAGE, CAT_WORKFLOWS, CAT_TYPE] @@ -188,7 +257,8 @@ PROP_TARBALL_URL = "tarball_url" # Publications PROP_TITLE = "title" - +# Assets from releases +# PROP_ASSETS = "assets" PROP_CONTENT_URL = "content_url" PROP_ENCODING_FORMAT = "encoding_format" PROP_UPLOAD_DATE = "upload_date" @@ -225,6 +295,7 @@ PUBLICATION = "Publication" LANGUAGE = "Programming_language" SOFTWARE_APPLICATION = "Software_application" +SCHOLARLY_ARTICLE = "Scholarly_article" # Different techniques TECHNIQUE_SUPERVISED_CLASSIFICATION = "supervised_classification" @@ -241,6 +312,11 @@ GITHUB_ACCEPT_HEADER = "application/vnd.github.v3+json" GITHUB_API = "https://api.github.com/repos" +# Software Heritage +SWH_ROOT = "https://archive.softwareheritage.org/" +REGEXP_SWH = r'\[\!\[SWH\]([^\]]+)\]\(([^)]+)\)' +REGEXP_SWH_ANCHOR = r"anchor=(swh:1:[a-z]+:[a-f0-9]{40})" +REGEXP_SWH_ALL_IDENTIFIERS = r"(swh:1:[a-z]+:[a-f0-9]{40})" # Spdx url SPDX_BASE = "https://spdx.org/licenses/" @@ -263,7 +339,8 @@ CAT_FORKS_URLS: "forks_url", CAT_STARS: "stargazers_count", CAT_KEYWORDS: "topics", - CAT_FORK_COUNTS: "forks_count" + CAT_FORK_COUNTS: "forks_count", + CAT_HOMEPAGE: "homepage" } # Mapping for releases @@ -280,6 +357,7 @@ PROP_RELEASE_ID: 'id', PROP_DATE_CREATED: 'created_at', PROP_DATE_PUBLISHED: "published_at", + CAT_ASSETS: "assets" } release_gitlab_crosswalk_table = { @@ -294,6 +372,7 @@ PROP_RELEASE_ID: 'tag_name', PROP_DATE_CREATED: 'created_at', PROP_DATE_PUBLISHED: "released_at", + CAT_ASSETS: "assets" } release_assets_github = { @@ -314,6 +393,23 @@ CAT_CONTACT, CAT_DESCRIPTION, CAT_CONTRIBUTORS, CAT_DOCUMENTATION, CAT_LICENSE, CAT_USAGE, CAT_FAQ, CAT_SUPPORT, CAT_IDENTIFIER, CAT_HAS_BUILD_FILE, CAT_EXECUTABLE_EXAMPLE, CAT_KEYWORDS] +# Config to materialize with yarrrml.yml. +MAPPING_CONFIG = """ + [DataSource1] + mappings: $PATH + file_path: $DATA + """ + +# Config to materialize with rml.ttl. +MAPPING_CONFIG_DICT = """ + [DataSource1] + mappings: $PATH + """ + +# YML by default +# mapping_path = str(Path(__file__).parent.parent) + os.path.sep + "mapping" + os.path.sep + "yarrrml.yml" + +mapping_path = str(Path(__file__).parent.parent) + os.path.sep + "mapping" + os.path.sep + "rml.ttl" AUX_RELEASES_IDS = "releases_ids" @@ -326,4 +422,52 @@ class RepositoryType(Enum): workflow_extensions=('.ga','.cwl','.nf','.knwf','.t2flow','.dag','.kar','.wdl',".smk",".snake") code_extensions = (".jl",".sql",".ddl",".psql",".mysql",".oracle",".plsql",".py",".java",".jar",".bash",".sh",".cs",".dll",".cpp",".c",".php",".phtml",".ps1",".rs",".go",".kt",".rb",".pl",".lua",".dart",".groovy",".asm",".swift",".R",".r") ontology_extensions=(".rdf",".ttl",".owl",".nt",".owl2",".nq",".n3",".rdfs") -media_files=(".mp4",".mp3",".wav",".bmp",".gif",".png",".jpeg",".jpg",".svg",".webp",".xls",".xlsx",".ico",".webm",".wmv",".txt") \ No newline at end of file +media_files=(".mp4",".mp3",".wav",".bmp",".gif",".png",".jpeg",".jpg",".svg",".webp",".xls",".xlsx",".ico",".webm",".wmv",".txt") + +# Folders ignored in process_files.py/process_repository_files +IGNORED_DIRS = {"test", "tests", "node_modules", "venv", "__pycache__"} + +SIZE_DOWNLOAD_LIMIT_MB = 200 +DOWNLOAD_TIMEOUT_SECONDS = 120 + +# CODEMETA Categories. All start with CAT_CODEMETA +CAT_CODEMETA_AUTHOR = "author" +CAT_CODEMETA_BUILDINSTRUCTIONS = "buildInstructions" +CAT_CODEMETA_CODEREPOSITORY = "codeRepository" +CAT_CODEMETA_CONTINUOUSINTEGRATION = "continuousIntegration" +CAT_CODEMETA_DATECREATED = "dateCreated" +CAT_CODEMETA_DATEMODIFIED = "dateModified" +CAT_CODEMETA_DATEPUBLISHED = "datePublished" +CAT_CODEMETA_DESCRIPTION = "description" +CAT_CODEMETA_DEVELOPMENTSTATUS = "developmentStatus" +CAT_CODEMETA_DOWNLOADURL = "downloadUrl" +CAT_CODEMETA_ISSUETRACKER = "issueTracker" +CAT_CODEMETA_IDENTIFIER = "identifier" +CAT_CODEMETA_KEYWORDS = "keywords" +CAT_CODEMETA_LICENSE = "license" +CAT_CODEMETA_LOGO = "logo" +CAT_CODEMETA_NAME = "name" +CAT_CODEMETA_PROGRAMMINGLANGUAGE = "programmingLanguage" +CAT_CODEMETA_README = "readme" +CAT_CODEMETA_REFERENCEPUBLICATION = "referencePublication" +CAT_CODEMETA_RELEASENOTES = "releaseNotes" +CAT_CODEMETA_RUNTIMEPLATFORM = "runtimePlatform" +CAT_CODEMETA_SOFTWAREREQUIREMENTS = "softwareRequirements" +CAT_CODEMETA_SOFTWAREVERSION = "softwareVersion" +CAT_CODEMETA_URL = "url" + + +# DOCKER labels maintainer +# REGEXP_MAINTAINER_LABEL_OCI = r'^\s*LABEL\s+org\.opencontainers\.image\.authors\s*=\s*["\']?(.+?)["\']?\s*$' +REGEXP_MAINTAINER_LABEL_OCI = r'^\s*LABEL\s+org\.opencontainers\.image\.authors\s*=\s*["\']([^"\'\\]+)["\']?\s*(?:\\)?\s*$' +REGEXP_MAINTAINER_LABEL_FREE = r'^\s*LABEL\s+"?maintainer"?\s*=\s*["\']?(.+?)["\']?\s*$' +REGEXP_MAINTAINER = r'^\s*MAINTAINER\s+(.+)$' +REGEXP_DOCKER_TITLE = r'org\.opencontainers\.image\.title\s*=\s*"([^"]+)"' +REGEXP_DOCKER_DESCRIPTION = r'org\.opencontainers\.image\.description\s*=\s*"([^"]+)"' +REGEXP_DOCKER_LICENSES = r'org\.opencontainers\.image\.licenses\s*=\s*"([^"]+)"' +REGEXP_DOCKER_SOURCE = r'org\.opencontainers\.image\.source\s*=\s*"([^"]+)"' +REGEXP_DOCKER_URL = r'org\.opencontainers\.image\.url\s*=\s*"([^"]+)"' +REGEXP_DOCKER_VERSION = r'org\.opencontainers\.image\.version\s*=\s*"([^"]+)"' +REGEXP_DOCKER_DOCUMENTATION = r'org\.opencontainers\.image\.documentation\s*=\s*"([^"]+)"' +REGEXP_DOCKER_VENDOR = r'org\.opencontainers\.image\.vendor\s*=\s*"([^"]+)"' +REGEXP_DOCKER_CREATED_DATE = r'org\.opencontainers\.image\.created\s*=\s*"([^"]+)"' diff --git a/src/somef_core/utils/markdown_utils.py b/src/somef_core/utils/markdown_utils.py index e898d7d..6683c59 100644 --- a/src/somef_core/utils/markdown_utils.py +++ b/src/somef_core/utils/markdown_utils.py @@ -1,9 +1,11 @@ import logging from io import StringIO from markdown import Markdown +from markdown_it import MarkdownIt from ..utils import constants import re +logging.getLogger("markdown_it").setLevel(logging.WARNING) ## Markdown to plain text conversion: begin ## # code snippet from https://stackoverflow.com/a/54923798 @@ -20,13 +22,18 @@ def unmark_element(element, stream=None): # patching Markdown -Markdown.output_formats["plain"] = unmark_element -__md = Markdown(output_format="plain") -__md.stripTopLevelTags = False +# Markdown.output_formats["plain"] = unmark_element +# __md = Markdown(output_format="plain") +# __md.stripTopLevelTags = False - -def unmark(text): - return __md.convert(text) +_md = MarkdownIt() +def unmark(text: str) -> str: + tokens = _md.parse(text) + return "".join( + t.content for t in tokens if t.type == "inline" + ) +# def unmark(text): +# return __md.convert(text) def remove_bibtex(string_list): @@ -63,6 +70,10 @@ def remove_comments(html_text): ------- Markdown with no HTML comments """ - comment_pattern = r'' - html_without_comments = re.sub(comment_pattern, '', html_text, flags=re.DOTALL) + # comment_pattern = r'' + # # # comment_pattern = r'