diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 619fbd9..89363d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: - name: Check dependencies run: make doctor - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: .venv key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }} @@ -36,8 +36,8 @@ jobs: - name: Revert the changes to bin folder run: chmod 644 ./bin/* - - name: Check code - run: make check + # - name: Check code + # run: make check - name: Test code run: make test diff --git a/.github/workflows/publish-to-pypi-beta.yml b/.github/workflows/publish-to-pypi-beta.yml new file mode 100644 index 0000000..6ba8038 --- /dev/null +++ b/.github/workflows/publish-to-pypi-beta.yml @@ -0,0 +1,45 @@ +name: Publish to PyPI - beta tags + +on: + release: + types: [published] + push: + branches: + - staging + pull_request: + types: [closed] + branches: + - staging + workflow_dispatch: + +jobs: + release: + if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.11] + + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Setup Poetry + uses: Gr1N/setup-poetry@v8 + + - name: Install dependencies + run: poetry install + + - name: Setup poetry config + run: poetry config pypi-token.pypi "${{ secrets.PYPI_API_TOKEN }}" + + - name: Build package + run: poetry build + + - name: Publish package + run: poetry publish diff --git a/.github/workflows/publish-to-pypi.yml b/.github/workflows/publish-to-pypi.yml index e5db103..167bef1 100644 --- a/.github/workflows/publish-to-pypi.yml +++ b/.github/workflows/publish-to-pypi.yml @@ -14,6 +14,7 @@ on: jobs: release: + if: (!(github.event.action == 'closed' && github.event.pull_request.merged != true)) runs-on: ubuntu-latest strategy: matrix: diff --git a/.gitignore b/.gitignore index 68b29fa..f383504 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ Icon* # Temporary virtual environment files /.cache/ /.venv/ +venv/ tmp/ # Temporary server files diff --git a/README.md b/README.md index fd4188a..e56ba01 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ If you would like to update the package, please follow the instructions below. If you are using Anaconda, you can create a virtual environment with: ```bash - conda create -n pyfairdatatools-env python + conda create -n pyfairdatatools-env python=3.8 conda activate pyfairdatatools-env ``` diff --git a/dev/changes/clinicaltrials.md b/dev/changes/clinicaltrials.md new file mode 100644 index 0000000..81a056e --- /dev/null +++ b/dev/changes/clinicaltrials.md @@ -0,0 +1,182 @@ +# All Changes + +- `IdentificationModule` has been renamed to `identificationModule` + - `officialTitle` has been added + - `acronym` has been added + - `OrgStudyIdInfo` has been renamed to `orgStudyIdInfo` + - `OrgStudyId` has been renamed to `orgStudyId` + - `OrgStudyIdType` has been renamed to `orgStudyIdType` + - `OrgStudyIdDomain` has been renamed to `orgStudyIdDomain` + - `OrgStudyIdLink` has been renamed to `orgStudyIdLink` + - `SecondaryIdInfoList` has been renamed to `secondaryIdInfoList` + - `SecondaryId` has been renamed to `secondaryId` + - `SecondaryIdType` has been renamed to `secondaryIdType` + - `SecondaryIdDomain` has been renamed to `secondaryIdDomain` + - `SecondaryIdLink` has been renamed to `secondaryIdLink` +- `StatusModule` has been renamed to `statusModule` + - `OverallStatus` has been renamed to `overallStatus` + - `WhyStopped` has been renamed to `whyStopped` + - `StartDateStruct` has been renamed to `startDateStruct` + - `StartDate` has been renamed to `startDate` and the format has been changed to `YYYY-MM` + - `StartDateType` has been renamed to `startDateType` + - `CompletionDateStruct` has been renamed to `completionDateStruct` and is now required + - `CompletionDate` has been renamed to `completionDate` and the format has been changed to `YYYY-MM` + - `CompletionDateType` has been renamed to `completionDateType` +- `SponsorCollaboratorsModule` has been renamed to `sponsorCollaboratorsModule` + - `LeadSponsor` has been renamed to `leadSponsor` + - `LeadSponsorName` has been renamed to `leadSponsorName` + - `leadSponsorIdentifier` has been added + - `leadSponsorIdentifierValue` has been added and is now required + - `leadSponsorIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `ResponsibleParty` has been renamed to `responsibleParty` + - `ResponsiblePartyInvestigatorFullName` has been removed and replaced with `responsiblePartyInvestigatorFirstName` and `responsiblePartyInvestigatorLastName` + - `responsiblePartyInvestigatorFirstName` has been added and is now required + - `responsiblePartyInvestigatorLastName` has been added and is now required + - `ResponsiblePartyInvestigatorTitle` has been renamed to `responsiblePartyInvestigatorTitle` + - `responsiblePartyInvestigatorIdentifier` has been added and is now required + - `responsiblePartyInvestigatorIdentifierValue` has been added and is now required + - `responsiblePartyInvestigatorIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `ResponsiblePartyInvestigatorAffiliation` has been renamed to `responsiblePartyInvestigatorAffiliation` + - `responsiblePartyInvestigatorAffiliationName` has been added and is now required + - `responsiblePartyInvestigatorAffiliationIdentifier` has been added + - `responsiblePartyInvestigatorAffiliationIdentifierValue` has been added and is now required + - `responsiblePartyInvestigatorAffiliationIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `CollaboratorList` has been renamed to `collaboratorList` + - `CollaboratorName` has been renamed to `collaboratorName` + - `collaboratorNameIdentifier` has been added + - `collaboratorNameIdentifierValue` has been added and is now required + - `collaboratorNameIdentifierScheme` has been added and is now required + - `schemeURI` has been added +- `OversightModule` has been renamed to `oversightModule` + - `OversightHasDMC` has been renamed to `oversightHasDMC` + - `isFDARegulatedDrug` has been added + - `isFDARegulatedDevice` has been added + - `humanSubjectReviewStatus` has been added and is now required +- `DescriptionModule` has been renamed to `descriptionModule` + - `BriefSummary` has been renamed to `briefSummary` + - `DetailedDescription` has been renamed to `detailedDescription` +- `ConditionsModule` has been renamed to `conditionsModule` + - `ConditionList` has been renamed to `conditionList` + - `conditionName` has been added and is now required + - `conditionIdentifier` has been added + - `conditionClassificationCode` has been added and is now required + - `conditionScheme` has been added and is now required + - `schemeURI` has been added + - `conditionURI` has been added + - `KeywordList` has been renamed to `keywordList` + - `keywordValue` has been added and is now required + - `keywordIdentifier` has been added + - `keywordClassificationCode` has been added and is now required + - `keywordScheme` has been added and is now required + - `schemeURI` has been added + - `keywordURI` has been added +- `DesignModule` has been renamed to `designModule` + - `StudyType` has been renamed to `studyType` + - `DesignInfo` has been renamed to `designInfo` + - `DesignAllocation` has been renamed to `designAllocation` + - `DesignInterventionModel` has been renamed to `designInterventionModel` + - `DesignInterventionModelDescription` has been renamed to `designInterventionModelDescription` + - `DesignObservationalModelList` has been renamed to `designObservationalModelList` + - `DesignTimePerspectiveList` has been renamed to `designTimePerspectiveList` + - `DesignPrimaryPurpose` has been renamed to `designPrimaryPurpose` + - `DesignMaskingInfo` has been renamed to `designMaskingInfo` + - `DesignMasking` has been renamed to `designMasking` + - `DesignMaskingDescription` has been renamed to `designMaskingDescription` + - `PhaseList` has been renamed to `phaseList` + - `EnrollmentInfo` has been renamed to `enrollmentInfo` + - `EnrollmentCount` has been renamed to `enrollmentCount` + - `EnrollmentType` has been renamed to `enrollmentType` + - `isPatientRegistry` has been added + - `BioSpec` has been renamed to `bioSpec` + - `BioSpecRetention` has been renamed to `bioSpecRetention` + - `BioSpecDescription` has been renamed to `bioSpecDescription` and is now required + - `TargetDuration` has been renamed to `targetDuration` and now requires a regex pattern and is required if `isPatientRegistry` is true + - `NumberGroupsCohorts` has been renamed to `numberGroupsCohorts` and has an updated regex pattern +- `ArmsInterventionsModule` has been renamed to `armsInterventionsModule` + - `ArmGroupList` has been renamed to `armGroupList` + - `ArmGroupLabel` has been renamed to `armGroupLabel` + - `ArmGroupType` has been renamed to `armGroupType` + - `ArmGroupDescription` has been renamed to `armGroupDescription` and is now required + - `ArmGroupInterventionList` has been renamed to `armGroupInterventionList` + - `InterventionList` has been renamed to `interventionList` + - `InterventionType` has been renamed to `interventionType` + - `InterventionName` has been renamed to `interventionName` + - `InterventionDescription` has been renamed to `interventionDescription` and is now required + - `InterventionOtherNameList` has been renamed to `interventionOtherNameList` +- `EligibilityModule` has been renamed to `eligibilityModule` + - `Gender` has been renamed to `sex` + - `GenderBased` has been renamed to `genderBased` + - `GenderDescription` has been renamed to `genderDescription` + - `MinimumAge` has been renamed to `minimumAge` + - `MaximumAge` has been renamed to `maximumAge` + - `HealthyVolunteers` has been renamed to `healthyVolunteers` + - `EligibilityCriteria` has been renamed to `eligibilityCriteria` + - `eligibilityCriteriaInclusion` has been added + - `eligibilityCriteriaExclusion` has been added + - `studyPopulation` has been added + - `samplingMethod` has been added +- `ContactsLocationsModule` has been renamed to `contactsLocationsModule` + - `CentralContactList` has been renamed to `centralContactList` + - `CentralContactName` has been removed and replaced with `centralContactFirstName` and `centralContactLastName` + - `CentralContactFirstName` has been added and is now required + - `CentralContactLastName` has been added and is now required + - `centralContactDegree` has been added + - `centralContactIdentifier` has been added + - `centralContactIdentifierValue` has been added and is now required + - `centralContactIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `centralContactAffiliation` has been added + - `centralContactAffiliationName` has been added and is now required + - `centralContactAffiliationIdentifier` has been added + - `centralContactAffiliationIdentifierValue` has been added and is now required + - `centralContactAffiliationIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `CentralContactPhone` has been renamed to `centralContactPhone` is no longer required + - `CentralContactPhoneExt` has been renamed to `centralContactPhoneExt` + - `CentralContactEMail` has been renamed to `centralContactEMail` + - `OverallOfficialList` has been renamed to `overallOfficialList` + - `OverallOfficialName` has been removed and replaced with `overallOfficialFirstName` and `overallOfficialLastName` + - `OverallOfficialFirstName` has been added and is now required + - `OverallOfficialLastName` has been added and is now required + - `overallOfficialDegree` has been added + - `overallOfficialIdentifier` has been added + - `overallOfficialIdentifierValue` has been added and is now required + - `overallOfficialIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `overallOfficialAffiliation` has been added + - `overallOfficialAffiliationName` has been added and is now required + - `overallOfficialAffiliationIdentifier` has been added + - `overallOfficialAffiliationIdentifierValue` has been added and is now required + - `overallOfficialAffiliationIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `OverallOfficialRole` has been renamed to `overallOfficialRole` + - `LocationList` has been renamed to `locationList` + - `LocationFacility` has been renamed to `locationFacility` + - `LocationStatus` has been renamed to `locationStatus` + - `LocationCity` has been renamed to `locationCity` + - `LocationState` has been renamed to `locationState` + - `LocationZip` has been renamed to `locationZip` + - `LocationCountry` has been renamed to `locationCountry` + - `locationIdentifier` has been added + - `locationIdentifierValue` has been added and is now required + - `locationIdentifierScheme` has been added and is now required + - `schemeURI` has been added + - `LocationContactList` has been renamed to `locationContactList` + - `LocationContactName` has been removed and replaced with `locationContactFirstName` and `locationContactLastName` + - `LocationContactFirstName` has been added and is now required + - `LocationContactLastName` has been added and is now required + - `locationContactDegree` has been added + - `locationContactIdentifier` has been added + - `locationContactIdentifierValue` has been added and is now required + - `locationContactIdentifierScheme` has been added + - `schemeURI` has been added + - `LocationContactRole` has been renamed to `locationContactRole` + - `LocationContactPhone` has been renamed to `locationContactPhone` + - `LocationContactPhoneExt` has been renamed to `locationContactPhoneExt` + - `LocationContactEMail` has been renamed to `locationContactEMail` +- `IPDSharingStatementModule` has been removed +- `ReferencesModule` has been removed +- `humanSubjectReviewStatus` has controlled options diff --git a/dev/changes/datacite.md b/dev/changes/datacite.md new file mode 100644 index 0000000..874a858 --- /dev/null +++ b/dev/changes/datacite.md @@ -0,0 +1,69 @@ +# All Changes + +- `Identifier` has been renamed to `identifier` +- `Title` has been renamed to `title` +- `Version` has been renamed to `version` +- `AlternateIdentifier` has been renamed to `alternateIdentifier` +- `Creator` has been renamed to `creator` + - `affiliationValue` has been renamed to `affiliationName` + - `affiliationName` has been renamed to required + - `affiliationIdentifier` has been changed to an object + - `affiliationIdentifierValue` has been added and is required + - `affiliationIdentifierScheme` has been added and is required + - `schemeURI` has been added +- `Contributor` has been renamed to `contributor` + - `affiliationValue` has been renamed to `affiliationName` + - `affiliationName` has been renamed to required + - `affiliationIdentifier` has been changed to an object + - `affiliationIdentifierValue` has been added and is required + - `affiliationIdentifierScheme` has been added and is required + - `schemeURI` has been added +- `PublicationYear` has been renamed to `publicationYear` +- `Date` has been renamed to `date` +- `ResourceType` has been renamed to `resourceType` +- `DatasetRecordKeys` has been removed +- `DatasetDeIdentLevel` has been renamed to `datasetDeIdentLevel` + - `NotKnown` has been removed as an option for `deIdentType` +- `DatasetConsent` has been renamed to `datasetConsent` + - `NotKnown` has been removed as an option for `consentType` +- `Description` has been renamed to `description` + - `SeriesInformation` has been removed as an option for `descriptionType` + - `TableOfContents` has been removed as an option for `descriptionType` +- `Language` has been renamed to `language` +- `RelatedIdentifier` has been renamed to `relatedIdentifier` and added to the libarary + - `relatedIdentifierValue` has been added and is required + - `relatedIdentifierType` has been added and is required + - `relationType` has been added and is required + - `relatedMetadataScheme` has been added + - `schemeURI` has been added + - `schemeType` has been added + - `resourceTypeGeneral` has been added +- `Subject` has been renamed to `subject` + - `subjectIdentifier` has been added + - `classificationCode` has been added and is required + - `subjectScheme` has been added and is required + - `schemeURI` has been added + - `valueURI` has been moved to here +- `ManagingOrganization` has been renamed to `managingOrganization` +- `AccessType` has been renamed to `accessType` + - `NotYetKnown` has been removed as an option for `accessType` +- `AcessDetails` has been renamed to `accessDetails` +- `Rights` has been renamed to `rights` + - `rightsValue` has been renamed to `rightsName` + - `rightsIdentifier` has been changed to an object + - `rightsIdentifierValue` has been added and is required + - `rightsIdentifierScheme` has been added and is required + - `schemeURI` has been added +- `Publisher` has been renamed to `publisher` + - `publisherName` has been added and is required + - `publisherIdentifier` has been changed to an object + - `publisherIdentifierValue` has been added and is required + - `publisherIdentifierScheme` has been added and is required + - `schemeURI` has been added +- `Size` has been renamed to `size` +- `format` has been added +- `FundingReference` has been renamed to `fundingReference` + - `funderIdentifierType` is now required in `funderIdentifier` +- `RelatedItem` has been removed +- `other` option has been renamed to `Other` for `identifierType` +- `Study lead` option has been renamed to `StudyLead` for `contributorType` diff --git a/dev/pull_schemas.py b/dev/pull_schemas.py new file mode 100644 index 0000000..3bf74a4 --- /dev/null +++ b/dev/pull_schemas.py @@ -0,0 +1,46 @@ +"""Pulls A JSON schema from a URL and saves it to a filepath""" + +import json +import requests + +schema_paths = [ + { + "sourceURL": "https://raw.githubusercontent.com/AI-READI/cds-specification/main/docs/schemas/dataset_description.schema.json", # noqa: E501 # pylint: disable=line-too-long + "destinationFileName": "dataset_description.schema.json", + }, + { + "sourceURL": "https://raw.githubusercontent.com/AI-READI/cds-specification/main/docs/schemas/study_description.schema.json", # noqa: E501 # pylint: disable=line-too-long + "destinationFileName": "study_description.schema.json", + }, + { + "sourceURL": "https://raw.githubusercontent.com/AI-READI/datatype-dictionary/main/datatype_dictionary.schema.json", # noqa: E501 # pylint: disable=line-too-long + "destinationFileName": "datatype_dictionary.schema.json", + }, +] + + +def main(): + """CLI entrypoint.""" + + folder_path = "pyfairdatatools/schemas/" + + for schema_path in schema_paths: + file_path = folder_path + schema_path["destinationFileName"] + + print(f"Pulling {schema_path['sourceURL']} to {file_path}") + + # Pull the schema from the URL + response = requests.get( + schema_path["sourceURL"], allow_redirects=True, timeout=10 + ) + schema = response.json() + + # Write the schema to a file + with open(file_path, "w", encoding="utf-8") as file: + json.dump(schema, file, indent=2) + + return + + +if __name__ == "__main__": # pragma: no cover + main() # pylint: disable=no-value-for-parameter diff --git a/docs/modules/generate.md b/docs/modules/generate.md index de1cac1..2e7f5ad 100644 --- a/docs/modules/generate.md +++ b/docs/modules/generate.md @@ -30,7 +30,7 @@ Provide the data required for your `dataset_description` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [dataset_description](../schemas/dataset_description.md) schema. +More information about the required data can be found in the [dataset_description](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/dataset_description.schema.json) schema. ##### file_path @@ -60,9 +60,9 @@ Provide the file type of the file where you want to save the generated dataset_d from pyfairdatatools import generate data = { - "Title": "My Dataset", - "Identifier": "10.5281/zenodo.1234567", - "IdentifierType": "DOI" + "title": "My Dataset", + "identifier": "10.5281/zenodo.1234567", + "identifierType": "DOI" } output = generate.generate_dataset_description(data = data, file_path = "dataset_description.json", file_type = "json") @@ -74,6 +74,10 @@ print(output) # dataset_description.json You can call the `generate_study_description` method to generate a study_description file. +#### Generate Study Description from Clinical Trial integration + +You can call the `generate_study_description_from_clinical_trials` method to generate an initial study_description file. + #### Parameters ##### data @@ -84,7 +88,7 @@ Provide the data required for your `study_description` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [study_description](../schemas/study_description.md) schema. +More information about the required data can be found in the [study_description](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/study_description.schema.json) schema. ##### file_path @@ -114,9 +118,9 @@ Provide the file type of the file where you want to save the generated study_des from pyfairdatatools import generate data = { - "Title": "My Dataset", - "Identifier": "10.5281/zenodo.1234567", - "IdentifierType": "DOI" + "title": "My Dataset", + "identifier": "10.5281/zenodo.1234567", + "identifierType": "DOI" } output = generate.generate_study_description(data = data, file_path = "study_description.json", file_type = "json") @@ -138,7 +142,7 @@ Provide the data required for your readme file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [readme](../schemas/readme.md) schema. +More information about the required data can be found in the [readme](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/readme.schema.json) schema. ##### file_path diff --git a/docs/modules/validate.md b/docs/modules/validate.md index 6a0a7d4..5ee5de2 100644 --- a/docs/modules/validate.md +++ b/docs/modules/validate.md @@ -30,9 +30,9 @@ Provide the data required for your `dataset_description` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [dataset_description](https://github.com/AI-READI/high-level-dataset-structure/blob/specifications/main/v1.0.0/schemas/dataset_description.schema.json) schema. +More information about the required data can be found in the [dataset_description](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/dataset_description.schema.json) schema. -You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlcv1) if you want a better understanding or visualization of the schema for the input. +You can the hosted validator [here](https://www.jsonschemavalidator.net/s/Uaohwh1p) if you want a better understanding or visualization of the schema for the input. #### Returns @@ -46,9 +46,9 @@ You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlc from pyfairdatatools import validate data = { - "Title": "My Dataset", - "Identifier": "10.5281/zenodo.1234567", - "IdentifierType": "DOI" + "title": "My Dataset", + "identifier": "10.5281/zenodo.1234567", + "identifierType": "DOI" } output = validate.validate_dataset_description(data = data) @@ -70,9 +70,9 @@ Provide the data required for your `study_description` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [study_description](https://github.com/AI-READI/high-level-dataset-structure/blob/specifications/main/v1.0.0/schemas/dataset_description.schema.json) schema. +More information about the required data can be found in the [study_description](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/study_description.schema.json) schema. -You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlcv1) if you want a better understanding or visualization of the schema for the input. +You can host the validator [here](https://www.jsonschemavalidator.net/s/pfpR4Klf) if you want a better understanding or visualization of the schema for the input. #### Returns @@ -110,9 +110,9 @@ Provide the data required for your `README` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [README](../schemas/README.md) schema. +More information about the required data can be found in the [README](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/readme.schema.json) schema. -You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlcv1) if you want a better understanding or visualization of the schema for the input. +You can host the validator [here](https://www.jsonschemavalidator.net/s/qGe6d1wH) if you want a better understanding or visualization of the schema for the input. #### Returns @@ -126,9 +126,9 @@ You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlc from pyfairdatatools import validate data = { - "Title": "My Dataset", - "Identifier": "10.5281/zenodo.1234567", - "Version": "1.0.0", + "title": "My Dataset", + "identifier": "10.5281/zenodo.1234567", + "version": "1.0.0", } output = validate.validate_readme(data = data) @@ -184,9 +184,9 @@ Provide the data required for your `participants.tsv` file in this paramater. | ------ | ------------- | -------- | ------------------------------------------ | | Object | {} | yes | Data object following the required schemas | -More information about the required data can be found in the [participants](../schemas/participants.md) schema. +More information about the required data can be found in the [participants](https://github.com/AI-READI/pyfairdatatools/blob/main/pyfairdatatools/schemas/participants.schema.json) schema. -You can the hosted validator [here](https://www.jsonschemavalidator.net/s/aNSmlcv1) if you want a better understanding or visualization of the schema for the input. +You can host the validator [here](https://www.jsonschemavalidator.net/s/AGbykeCI) if you want a better understanding or visualization of the schema for the input. #### Returns diff --git a/poetry.lock b/poetry.lock index 26c7c5d..3cf3065 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,133 +2,38 @@ [[package]] name = "altgraph" -version = "0.17.3" +version = "0.17.4" description = "Python graph (network) package" category = "dev" optional = false python-versions = "*" files = [ - {file = "altgraph-0.17.3-py2.py3-none-any.whl", hash = "sha256:c8ac1ca6772207179ed8003ce7687757c04b0b71536f81e2ac5755c6226458fe"}, - {file = "altgraph-0.17.3.tar.gz", hash = "sha256:ad33358114df7c9416cdb8fa1eaa5852166c505118717021c6a8c7c7abbd03dd"}, + {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, + {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, ] -[[package]] -name = "anyio" -version = "3.7.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "anyio-3.7.0-py3-none-any.whl", hash = "sha256:eddca883c4175f14df8aedce21054bfca3adb70ffe76a9f607aef9d7fa2ea7f0"}, - {file = "anyio-3.7.0.tar.gz", hash = "sha256:275d9973793619a5374e1c89a4f4ad3f4b0a5510a2b5b939444bee8f4c4d37ce"}, -] - -[package.dependencies] -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=6.1.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme", "sphinxcontrib-jquery"] -test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] -trio = ["trio (<0.22)"] - [[package]] name = "appnope" -version = "0.1.3" +version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" category = "dev" optional = false -python-versions = "*" -files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, -] - -[[package]] -name = "argon2-cffi" -version = "21.3.0" -description = "The secure Argon2 password hashing algorithm." -category = "dev" -optional = false python-versions = ">=3.6" files = [ - {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, - {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, ] -[package.dependencies] -argon2-cffi-bindings = "*" - -[package.extras] -dev = ["cogapp", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "pre-commit", "pytest", "sphinx", "sphinx-notfound-page", "tomli"] -docs = ["furo", "sphinx", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] - -[[package]] -name = "argon2-cffi-bindings" -version = "21.2.0" -description = "Low-level CFFI bindings for Argon2" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, - {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, - {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, - {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, - {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, -] - -[package.dependencies] -cffi = ">=1.0.1" - -[package.extras] -dev = ["cogapp", "pre-commit", "pytest", "wheel"] -tests = ["pytest"] - -[[package]] -name = "arrow" -version = "1.2.3" -description = "Better dates & times for Python" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "arrow-1.2.3-py3-none-any.whl", hash = "sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2"}, - {file = "arrow-1.2.3.tar.gz", hash = "sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1"}, -] - -[package.dependencies] -python-dateutil = ">=2.7.0" - [[package]] name = "art" -version = "6.0" +version = "6.1" description = "ASCII Art Library For Python" category = "main" optional = false python-versions = ">=3.5" files = [ - {file = "art-6.0-py3-none-any.whl", hash = "sha256:882e6b5a4c6045c6dace31147c0b8522c8ca70177a5922f172733d116123a187"}, - {file = "art-6.0.tar.gz", hash = "sha256:884ef1c10e900387cce97789e8668125720cbf4459206641b91fc298c859cda9"}, + {file = "art-6.1-py3-none-any.whl", hash = "sha256:159819c418001467f8d79616fa0814277deac97c8a363d1eb3e7c0a31526bfc3"}, + {file = "art-6.1.tar.gz", hash = "sha256:6ab3031e3b7710039e73497b0e750cadfe04d4c1279ce3a123500dbafb9e1b64"}, ] [package.extras] @@ -156,22 +61,23 @@ wrapt = [ [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[tests]", "pre-commit"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "backcall" @@ -185,25 +91,6 @@ files = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] -[[package]] -name = "beautifulsoup4" -version = "4.12.2" -description = "Screen-scraping library" -category = "dev" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.2-py3-none-any.whl", hash = "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a"}, - {file = "beautifulsoup4-4.12.2.tar.gz", hash = "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - [[package]] name = "black" version = "22.12.0" @@ -240,209 +127,128 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] -[[package]] -name = "bleach" -version = "6.0.0" -description = "An easy safelist-based HTML-sanitizing tool." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "bleach-6.0.0-py3-none-any.whl", hash = "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4"}, - {file = "bleach-6.0.0.tar.gz", hash = "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414"}, -] - -[package.dependencies] -six = ">=1.9.0" -webencodings = "*" - -[package.extras] -css = ["tinycss2 (>=1.1.0,<1.2)"] - [[package]] name = "certifi" -version = "2023.5.7" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, - {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] -[[package]] -name = "cffi" -version = "1.15.1" -description = "Foreign Function Interface for Python calling C code." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"}, - {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"}, - {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"}, - {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"}, - {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"}, - {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"}, - {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"}, - {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"}, - {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"}, - {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"}, - {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"}, - {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"}, - {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"}, - {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"}, - {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"}, - {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"}, - {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"}, - {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"}, - {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"}, - {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"}, - {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"}, - {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"}, - {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"}, - {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"}, - {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"}, - {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"}, - {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"}, - {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"}, - {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"}, - {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"}, - {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"}, - {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"}, - {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"}, -] - -[package.dependencies] -pycparser = "*" - [[package]] name = "charset-normalizer" -version = "3.1.0" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [package.dependencies] @@ -460,94 +266,66 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "comm" -version = "0.1.3" -description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "comm-0.1.3-py3-none-any.whl", hash = "sha256:16613c6211e20223f215fc6d3b266a247b6e2641bf4e0a3ad34cb1aff2aa3f37"}, - {file = "comm-0.1.3.tar.gz", hash = "sha256:a61efa9daffcfbe66fd643ba966f846a624e4e6d6767eda9cf6e993aadaab93e"}, -] - -[package.dependencies] -traitlets = ">=5.3" - -[package.extras] -lint = ["black (>=22.6.0)", "mdformat (>0.7)", "mdformat-gfm (>=0.3.5)", "ruff (>=0.0.156)"] -test = ["pytest"] -typing = ["mypy (>=0.990)"] - [[package]] name = "coverage" -version = "7.2.7" +version = "7.4.3" description = "Code coverage measurement for Python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"}, - {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"}, - {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"}, - {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"}, - {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"}, - {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"}, - {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"}, - {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"}, - {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"}, - {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"}, - {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"}, - {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"}, - {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"}, - {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"}, - {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"}, - {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"}, - {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"}, - {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"}, - {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"}, - {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"}, - {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"}, - {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"}, - {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"}, - {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"}, - {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"}, - {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"}, - {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"}, - {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"}, - {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"}, - {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"}, - {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"}, - {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"}, - {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, + {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, + {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, + {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, + {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, + {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, + {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, + {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, + {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, + {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, + {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, + {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, + {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, + {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, + {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, + {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, + {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, + {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, + {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, + {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, + {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, + {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, + {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, + {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, + {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, + {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, + {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, + {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, ] [package.dependencies] @@ -575,34 +353,6 @@ docopt = ">=0.6" minilog = ">=2.0" requests = ">=2.28,<3.0" -[[package]] -name = "debugpy" -version = "1.6.7" -description = "An implementation of the Debug Adapter Protocol for Python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "debugpy-1.6.7-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b3e7ac809b991006ad7f857f016fa92014445085711ef111fdc3f74f66144096"}, - {file = "debugpy-1.6.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3876611d114a18aafef6383695dfc3f1217c98a9168c1aaf1a02b01ec7d8d1e"}, - {file = "debugpy-1.6.7-cp310-cp310-win32.whl", hash = "sha256:33edb4afa85c098c24cc361d72ba7c21bb92f501104514d4ffec1fb36e09c01a"}, - {file = "debugpy-1.6.7-cp310-cp310-win_amd64.whl", hash = "sha256:ed6d5413474e209ba50b1a75b2d9eecf64d41e6e4501977991cdc755dc83ab0f"}, - {file = "debugpy-1.6.7-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:38ed626353e7c63f4b11efad659be04c23de2b0d15efff77b60e4740ea685d07"}, - {file = "debugpy-1.6.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279d64c408c60431c8ee832dfd9ace7c396984fd7341fa3116aee414e7dcd88d"}, - {file = "debugpy-1.6.7-cp37-cp37m-win32.whl", hash = "sha256:dbe04e7568aa69361a5b4c47b4493d5680bfa3a911d1e105fbea1b1f23f3eb45"}, - {file = "debugpy-1.6.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f90a2d4ad9a035cee7331c06a4cf2245e38bd7c89554fe3b616d90ab8aab89cc"}, - {file = "debugpy-1.6.7-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5224eabbbeddcf1943d4e2821876f3e5d7d383f27390b82da5d9558fd4eb30a9"}, - {file = "debugpy-1.6.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae1123dff5bfe548ba1683eb972329ba6d646c3a80e6b4c06cd1b1dd0205e9b"}, - {file = "debugpy-1.6.7-cp38-cp38-win32.whl", hash = "sha256:9cd10cf338e0907fdcf9eac9087faa30f150ef5445af5a545d307055141dd7a4"}, - {file = "debugpy-1.6.7-cp38-cp38-win_amd64.whl", hash = "sha256:aaf6da50377ff4056c8ed470da24632b42e4087bc826845daad7af211e00faad"}, - {file = "debugpy-1.6.7-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:0679b7e1e3523bd7d7869447ec67b59728675aadfc038550a63a362b63029d2c"}, - {file = "debugpy-1.6.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de86029696e1b3b4d0d49076b9eba606c226e33ae312a57a46dca14ff370894d"}, - {file = "debugpy-1.6.7-cp39-cp39-win32.whl", hash = "sha256:d71b31117779d9a90b745720c0eab54ae1da76d5b38c8026c654f4a066b0130a"}, - {file = "debugpy-1.6.7-cp39-cp39-win_amd64.whl", hash = "sha256:c0ff93ae90a03b06d85b2c529eca51ab15457868a377c4cc40a23ab0e4e552a3"}, - {file = "debugpy-1.6.7-py2.py3-none-any.whl", hash = "sha256:53f7a456bc50706a0eaabecf2d3ce44c4d5010e46dfc65b6b81a518b42866267"}, - {file = "debugpy-1.6.7.zip", hash = "sha256:c4c2f0810fa25323abfdfa36cbbbb24e5c3b1a42cb762782de64439c575d67f2"}, -] - [[package]] name = "decorator" version = "5.1.1" @@ -615,18 +365,6 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - [[package]] name = "dicttoxml" version = "1.7.16" @@ -641,18 +379,19 @@ files = [ [[package]] name = "dill" -version = "0.3.6" -description = "serialize all of python" +version = "0.3.8" +description = "serialize all of Python" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, - {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, ] [package.extras] graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] [[package]] name = "docopt" @@ -667,56 +406,29 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.1" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, - {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] test = ["pytest (>=6)"] -[[package]] -name = "fastjsonschema" -version = "2.17.1" -description = "Fastest Python implementation of JSON schema" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "fastjsonschema-2.17.1-py3-none-any.whl", hash = "sha256:4b90b252628ca695280924d863fe37234eebadc29c5360d322571233dc9746e0"}, - {file = "fastjsonschema-2.17.1.tar.gz", hash = "sha256:f4eeb8a77cef54861dbf7424ac8ce71306f12cbb086c45131bcba2c6a4f726e3"}, -] - -[package.extras] -devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] - -[[package]] -name = "fqdn" -version = "1.5.1" -description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" -files = [ - {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, - {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, -] - [[package]] name = "freezegun" -version = "1.2.2" +version = "1.4.0" description = "Let your Python tests travel through time" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"}, - {file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"}, + {file = "freezegun-1.4.0-py3-none-any.whl", hash = "sha256:55e0fc3c84ebf0a96a5aa23ff8b53d70246479e9a68863f1fcac5a3e52f19dd6"}, + {file = "freezegun-1.4.0.tar.gz", hash = "sha256:10939b0ba0ff5adaecf3b06a5c2f73071d9678e507c5eaedb23c761d56ac774b"}, ] [package.dependencies] @@ -742,54 +454,54 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" category = "dev" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] name = "importlib-metadata" -version = "6.6.0" +version = "7.0.1" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, - {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "importlib-resources" -version = "5.12.0" +version = "6.1.2" description = "Read resources from Python packages" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "importlib_resources-5.12.0-py3-none-any.whl", hash = "sha256:7b1deeebbf351c7578e09bf2f63fa2ce8b5ffec296e0d349139d43cca061a81a"}, - {file = "importlib_resources-5.12.0.tar.gz", hash = "sha256:4be82589bf5c1d7999aedf2a45159d10cb3ca4f19b2271f8792bc8e6da7b22f6"}, + {file = "importlib_resources-6.1.2-py3-none-any.whl", hash = "sha256:9a0a862501dc38b68adebc82970140c9e4209fc99601782925178f8386339938"}, + {file = "importlib_resources-6.1.2.tar.gz", hash = "sha256:308abf8474e2dba5f867d279237cd4076482c3de7104a40b41426370e891549b"}, ] [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["flake8 (<5)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-ruff (>=0.2.1)", "zipp (>=3.17)"] [[package]] name = "iniconfig" @@ -803,40 +515,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "ipykernel" -version = "6.23.3" -description = "IPython Kernel for Jupyter" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "ipykernel-6.23.3-py3-none-any.whl", hash = "sha256:bc00662dc44d4975b668cdb5fefb725e38e9d8d6e28441a519d043f38994922d"}, - {file = "ipykernel-6.23.3.tar.gz", hash = "sha256:dd4e18116357f36a1e459b3768412371bee764c51844cbf25c4ed1eb9cae4a54"}, -] - -[package.dependencies] -appnope = {version = "*", markers = "platform_system == \"Darwin\""} -comm = ">=0.1.1" -debugpy = ">=1.6.5" -ipython = ">=7.23.1" -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -matplotlib-inline = ">=0.1" -nest-asyncio = "*" -packaging = "*" -psutil = "*" -pyzmq = ">=20" -tornado = ">=6.1" -traitlets = ">=5.4.0" - -[package.extras] -cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] -pyqt5 = ["pyqt5"] -pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] - [[package]] name = "ipython" version = "7.34.0" @@ -874,103 +552,51 @@ parallel = ["ipyparallel"] qtconsole = ["qtconsole"] test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments", "requests", "testpath"] -[[package]] -name = "ipython-genutils" -version = "0.2.0" -description = "Vestigial utilities from IPython" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, - {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, -] - -[[package]] -name = "ipywidgets" -version = "8.0.6" -description = "Jupyter interactive widgets" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "ipywidgets-8.0.6-py3-none-any.whl", hash = "sha256:a60bf8d2528997e05ac83fd19ea2fbe65f2e79fbe1b2b35779bdfc46c2941dcc"}, - {file = "ipywidgets-8.0.6.tar.gz", hash = "sha256:de7d779f2045d60de9f6c25f653fdae2dba57898e6a1284494b3ba20b6893bb8"}, -] - -[package.dependencies] -ipykernel = ">=4.5.1" -ipython = ">=6.1.0" -jupyterlab-widgets = ">=3.0.7,<3.1.0" -traitlets = ">=4.3.1" -widgetsnbextension = ">=4.0.7,<4.1.0" - -[package.extras] -test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] - -[[package]] -name = "isoduration" -version = "20.11.0" -description = "Operations with ISO 8601 durations" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, - {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, -] - -[package.dependencies] -arrow = ">=0.15.0" - [[package]] name = "isort" -version = "5.12.0" +version = "5.13.2" description = "A Python utility / library to sort Python imports." category = "dev" optional = false python-versions = ">=3.8.0" files = [ - {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, - {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, ] [package.extras] -colors = ["colorama (>=0.4.3)"] -pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] -plugins = ["setuptools"] -requirements-deprecated-finder = ["pip-api", "pipreqs"] +colors = ["colorama (>=0.4.6)"] [[package]] name = "jedi" -version = "0.18.2" +version = "0.19.1" description = "An autocompletion tool for Python that can be used for text editors." category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "jedi-0.18.2-py2.py3-none-any.whl", hash = "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e"}, - {file = "jedi-0.18.2.tar.gz", hash = "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612"}, + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, ] [package.dependencies] -parso = ">=0.8.0,<0.9.0" +parso = ">=0.8.3,<0.9.0" [package.extras] docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jinja2" -version = "3.1.2" +version = "3.1.3" description = "A very fast and expressive template engine." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [package.dependencies] @@ -979,289 +605,91 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "jsonpointer" -version = "2.4" -description = "Identify specific nodes in a JSON document (RFC 6901)" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, -] - [[package]] name = "jsonschema" -version = "4.17.3" +version = "4.21.1" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, + {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"}, + {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"}, ] [package.dependencies] -attrs = ">=17.4.0" -fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +attrs = ">=22.2.0" importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} +jsonschema-specifications = ">=2023.03.6" pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" -rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} -uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} -webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} +referencing = ">=0.28.4" +rpds-py = ">=0.7.1" [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] [[package]] -name = "jupyter" -version = "1.0.0" -description = "Jupyter metapackage. Install all the Jupyter components in one go." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "jupyter-1.0.0-py2.py3-none-any.whl", hash = "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"}, - {file = "jupyter-1.0.0.tar.gz", hash = "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"}, - {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, -] - -[package.dependencies] -ipykernel = "*" -ipywidgets = "*" -jupyter-console = "*" -nbconvert = "*" -notebook = "*" -qtconsole = "*" - -[[package]] -name = "jupyter-client" -version = "8.3.0" -description = "Jupyter protocol implementation and client libraries" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_client-8.3.0-py3-none-any.whl", hash = "sha256:7441af0c0672edc5d28035e92ba5e32fadcfa8a4e608a434c228836a89df6158"}, - {file = "jupyter_client-8.3.0.tar.gz", hash = "sha256:3af69921fe99617be1670399a0b857ad67275eefcfa291e2c81a160b7b650f5f"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -python-dateutil = ">=2.8.2" -pyzmq = ">=23.0" -tornado = ">=6.2" -traitlets = ">=5.3" - -[package.extras] -docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] - -[[package]] -name = "jupyter-console" -version = "6.6.3" -description = "Jupyter terminal console" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485"}, - {file = "jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539"}, -] - -[package.dependencies] -ipykernel = ">=6.14" -ipython = "*" -jupyter-client = ">=7.0.0" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -prompt-toolkit = ">=3.0.30" -pygments = "*" -pyzmq = ">=17" -traitlets = ">=5.4" - -[package.extras] -test = ["flaky", "pexpect", "pytest"] - -[[package]] -name = "jupyter-core" -version = "5.3.1" -description = "Jupyter core package. A base package on which Jupyter projects rely." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_core-5.3.1-py3-none-any.whl", hash = "sha256:ae9036db959a71ec1cac33081eeb040a79e681f08ab68b0883e9a676c7a90dce"}, - {file = "jupyter_core-5.3.1.tar.gz", hash = "sha256:5ba5c7938a7f97a6b0481463f7ff0dbac7c15ba48cf46fa4035ca6e838aa1aba"}, -] - -[package.dependencies] -platformdirs = ">=2.5" -pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} -traitlets = ">=5.3" - -[package.extras] -docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] -test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "jupyter-events" -version = "0.6.3" -description = "Jupyter Event System library" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jupyter_events-0.6.3-py3-none-any.whl", hash = "sha256:57a2749f87ba387cd1bfd9b22a0875b889237dbf2edc2121ebb22bde47036c17"}, - {file = "jupyter_events-0.6.3.tar.gz", hash = "sha256:9a6e9995f75d1b7146b436ea24d696ce3a35bfa8bfe45e0c33c334c79464d0b3"}, -] - -[package.dependencies] -jsonschema = {version = ">=3.2.0", extras = ["format-nongpl"]} -python-json-logger = ">=2.0.4" -pyyaml = ">=5.3" -rfc3339-validator = "*" -rfc3986-validator = ">=0.1.1" -traitlets = ">=5.3" - -[package.extras] -cli = ["click", "rich"] -docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] -test = ["click", "coverage", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "pytest-cov", "rich"] - -[[package]] -name = "jupyter-server" -version = "2.7.0" -description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_server-2.7.0-py3-none-any.whl", hash = "sha256:6a77912aff643e53fa14bdb2634884b52b784a4be77ce8e93f7283faed0f0849"}, - {file = "jupyter_server-2.7.0.tar.gz", hash = "sha256:36da0a266d31a41ac335a366c88933c17dfa5bb817a48f5c02c16d303bc9477f"}, -] - -[package.dependencies] -anyio = ">=3.1.0" -argon2-cffi = "*" -jinja2 = "*" -jupyter-client = ">=7.4.4" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -jupyter-events = ">=0.6.0" -jupyter-server-terminals = "*" -nbconvert = ">=6.4.4" -nbformat = ">=5.3.0" -overrides = "*" -packaging = "*" -prometheus-client = "*" -pywinpty = {version = "*", markers = "os_name == \"nt\""} -pyzmq = ">=24" -send2trash = "*" -terminado = ">=0.8.3" -tornado = ">=6.2.0" -traitlets = ">=5.6.0" -websocket-client = "*" - -[package.extras] -docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] -test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "requests"] - -[[package]] -name = "jupyter-server-terminals" -version = "0.4.4" -description = "A Jupyter Server Extension Providing Terminals." -category = "dev" +name = "jsonschema-specifications" +version = "2023.12.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_server_terminals-0.4.4-py3-none-any.whl", hash = "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36"}, - {file = "jupyter_server_terminals-0.4.4.tar.gz", hash = "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d"}, + {file = "jsonschema_specifications-2023.12.1-py3-none-any.whl", hash = "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c"}, + {file = "jsonschema_specifications-2023.12.1.tar.gz", hash = "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc"}, ] [package.dependencies] -pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} -terminado = ">=0.8.3" - -[package.extras] -docs = ["jinja2", "jupyter-server", "mistune (<3.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] -test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] - -[[package]] -name = "jupyterlab-pygments" -version = "0.2.2" -description = "Pygments theme using JupyterLab CSS variables" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, - {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, -] - -[[package]] -name = "jupyterlab-widgets" -version = "3.0.7" -description = "Jupyter interactive widgets for JupyterLab" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jupyterlab_widgets-3.0.7-py3-none-any.whl", hash = "sha256:c73f8370338ec19f1bec47254752d6505b03601cbd5a67e6a0b184532f73a459"}, - {file = "jupyterlab_widgets-3.0.7.tar.gz", hash = "sha256:c3a50ed5bf528a0c7a869096503af54702f86dda1db469aee1c92dc0c01b43ca"}, -] +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +referencing = ">=0.31.0" [[package]] name = "lazy-object-proxy" -version = "1.9.0" +version = "1.10.0" description = "A fast and thorough lazy object proxy." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"}, - {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"}, - {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"}, - {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"}, - {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"}, - {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"}, + {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"}, + {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"}, + {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"}, + {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"}, + {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"}, + {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"}, + {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"}, ] [[package]] @@ -1277,14 +705,14 @@ files = [ [[package]] name = "macholib" -version = "1.16.2" +version = "1.16.3" description = "Mach-O header analysis and editing" category = "dev" optional = false python-versions = "*" files = [ - {file = "macholib-1.16.2-py2.py3-none-any.whl", hash = "sha256:44c40f2cd7d6726af8fa6fe22549178d3a4dfecc35a9cd15ea916d9c83a688e0"}, - {file = "macholib-1.16.2.tar.gz", hash = "sha256:557bbfa1bb255c20e9abafe7ed6cd8046b48d9525db2f9b77d3122a63a2a8bf8"}, + {file = "macholib-1.16.3-py2.py3-none-any.whl", hash = "sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c"}, + {file = "macholib-1.16.3.tar.gz", hash = "sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30"}, ] [package.dependencies] @@ -1310,62 +738,72 @@ testing = ["coverage", "pyyaml"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] @@ -1409,26 +847,14 @@ files = [ [[package]] name = "minilog" -version = "2.1" +version = "2.3" description = "Minimalistic wrapper for Python logging." category = "main" optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "minilog-2.1-py3-none-any.whl", hash = "sha256:0c48879cc9e72f0127aa2c36b522dc6fa10fa8532956197436b491d31617d5d5"}, - {file = "minilog-2.1.tar.gz", hash = "sha256:2048a8d381b36ef5f146fb9a657e627729411f8e2ed0047e2c1286cf8e3e58d7"}, -] - -[[package]] -name = "mistune" -version = "3.0.1" -description = "A sane and fast Markdown parser with useful plugins and renderers" -category = "dev" -optional = false -python-versions = ">=3.7" +python-versions = ">=3.8,<4.0" files = [ - {file = "mistune-3.0.1-py3-none-any.whl", hash = "sha256:b9b3e438efbb57c62b5beb5e134dab664800bdf1284a7ee09e8b12b13eb1aac6"}, - {file = "mistune-3.0.1.tar.gz", hash = "sha256:e912116c13aa0944f9dc530db38eb88f6a77087ab128f49f84a48f4c05ea163c"}, + {file = "minilog-2.3-py3-none-any.whl", hash = "sha256:e42dc2def1da424e90d6664279c128dde94adc5840557b27857957ed23ee09b6"}, + {file = "minilog-2.3.tar.gz", hash = "sha256:ebdf354f1dd86a2e8a824cdde4b7b50cdbc24b99a5465bc4d1806bd1e030bc92"}, ] [[package]] @@ -1460,295 +886,87 @@ i18n = ["babel (>=2.9.0)"] [[package]] name = "mypy" -version = "1.3.0" +version = "1.8.0" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.7" -files = [ - {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, - {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, - {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, - {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, - {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, - {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, - {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, - {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, - {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, - {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, - {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, - {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, - {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, - {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, - {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, - {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, - {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, - {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, - {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, - {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, - {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, - {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, - {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=3.10" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -python2 = ["typed-ast (>=1.4.0,<2)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "nbclassic" -version = "1.0.0" -description = "Jupyter Notebook as a Jupyter Server extension." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "nbclassic-1.0.0-py3-none-any.whl", hash = "sha256:f99e4769b4750076cd4235c044b61232110733322384a94a63791d2e7beacc66"}, - {file = "nbclassic-1.0.0.tar.gz", hash = "sha256:0ae11eb2319455d805596bf320336cda9554b41d99ab9a3c31bf8180bffa30e3"}, -] - -[package.dependencies] -argon2-cffi = "*" -ipykernel = "*" -ipython-genutils = "*" -jinja2 = "*" -jupyter-client = ">=6.1.1" -jupyter-core = ">=4.6.1" -jupyter-server = ">=1.8" -nbconvert = ">=5" -nbformat = "*" -nest-asyncio = ">=1.5" -notebook-shim = ">=0.2.3" -prometheus-client = "*" -pyzmq = ">=17" -Send2Trash = ">=1.8.0" -terminado = ">=0.8.3" -tornado = ">=6.1" -traitlets = ">=4.2.1" - -[package.extras] -docs = ["myst-parser", "nbsphinx", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] -json-logging = ["json-logging"] -test = ["coverage", "nbval", "pytest", "pytest-cov", "pytest-jupyter", "pytest-playwright", "pytest-tornasync", "requests", "requests-unixsocket", "testpath"] - -[[package]] -name = "nbclient" -version = "0.8.0" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." -category = "dev" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"}, - {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"}, -] - -[package.dependencies] -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -nbformat = ">=5.1" -traitlets = ">=5.4" - -[package.extras] -dev = ["pre-commit"] -docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] - -[[package]] -name = "nbconvert" -version = "7.6.0" -description = "Converting Jupyter Notebooks" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "nbconvert-7.6.0-py3-none-any.whl", hash = "sha256:5a445c6794b0791984bc5436608fe2c066cb43c83920c7bc91bde3b765e9a264"}, - {file = "nbconvert-7.6.0.tar.gz", hash = "sha256:24fcf27efdef2b51d7f090cc5ce5a9b178766a55be513c4ebab08c91899ab550"}, -] - -[package.dependencies] -beautifulsoup4 = "*" -bleach = "!=5.0.0" -defusedxml = "*" -importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} -jinja2 = ">=3.0" -jupyter-core = ">=4.7" -jupyterlab-pygments = "*" -markupsafe = ">=2.0" -mistune = ">=2.0.3,<4" -nbclient = ">=0.5.0" -nbformat = ">=5.7" -packaging = "*" -pandocfilters = ">=1.4.1" -pygments = ">=2.4.1" -tinycss2 = "*" -traitlets = ">=5.1" - -[package.extras] -all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] -docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] -qtpdf = ["nbconvert[qtpng]"] -qtpng = ["pyqtwebengine (>=5.15)"] -serve = ["tornado (>=6.1)"] -test = ["ipykernel", "ipywidgets (>=7)", "pre-commit", "pytest", "pytest-dependency"] -webpdf = ["pyppeteer (>=1,<1.1)"] - -[[package]] -name = "nbformat" -version = "5.9.0" -description = "The Jupyter Notebook format" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "nbformat-5.9.0-py3-none-any.whl", hash = "sha256:8c8fa16d6d05062c26177754bfbfac22de644888e2ef69d27ad2a334cf2576e5"}, - {file = "nbformat-5.9.0.tar.gz", hash = "sha256:e98ebb6120c3efbafdee2a40af2a140cadee90bb06dd69a2a63d9551fcc7f976"}, -] - -[package.dependencies] -fastjsonschema = "*" -jsonschema = ">=2.6" -jupyter-core = "*" -traitlets = ">=5.1" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["pep440", "pre-commit", "pytest", "testpath"] - -[[package]] -name = "nest-asyncio" -version = "1.5.6" -description = "Patch asyncio to allow nested event loops" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, - {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, -] - -[[package]] -name = "nose" -version = "1.3.7" -description = "nose extends unittest to make testing easier" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"}, - {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"}, - {file = "nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"}, -] - -[[package]] -name = "notebook" -version = "6.5.4" -description = "A web-based notebook environment for interactive computing" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "notebook-6.5.4-py3-none-any.whl", hash = "sha256:dd17e78aefe64c768737b32bf171c1c766666a21cc79a44d37a1700771cab56f"}, - {file = "notebook-6.5.4.tar.gz", hash = "sha256:517209568bd47261e2def27a140e97d49070602eea0d226a696f42a7f16c9a4e"}, -] - -[package.dependencies] -argon2-cffi = "*" -ipykernel = "*" -ipython-genutils = "*" -jinja2 = "*" -jupyter-client = ">=5.3.4" -jupyter-core = ">=4.6.1" -nbclassic = ">=0.4.7" -nbconvert = ">=5" -nbformat = "*" -nest-asyncio = ">=1.5" -prometheus-client = "*" -pyzmq = ">=17" -Send2Trash = ">=1.8.0" -terminado = ">=0.8.3" -tornado = ">=6.1" -traitlets = ">=4.2.1" - -[package.extras] -docs = ["myst-parser", "nbsphinx", "sphinx", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] -json-logging = ["json-logging"] -test = ["coverage", "nbval", "pytest", "pytest-cov", "requests", "requests-unixsocket", "selenium (==4.1.5)", "testpath"] - -[[package]] -name = "notebook-shim" -version = "0.2.3" -description = "A shim layer for notebook traits and config" -category = "dev" -optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "notebook_shim-0.2.3-py3-none-any.whl", hash = "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7"}, - {file = "notebook_shim-0.2.3.tar.gz", hash = "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, + {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, + {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, + {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, + {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, + {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, + {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, + {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, + {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, + {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, + {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, + {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, + {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, + {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, + {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, + {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, + {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, + {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, + {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, + {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, + {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, + {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, + {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, ] [package.dependencies] -jupyter-server = ">=1.8,<3" +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" [package.extras] -test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] [[package]] -name = "overrides" -version = "7.3.1" -description = "A decorator to automatically detect mismatch when overriding a method." +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.5" files = [ - {file = "overrides-7.3.1-py3-none-any.whl", hash = "sha256:6187d8710a935d09b0bcef8238301d6ee2569d2ac1ae0ec39a8c7924e27f58ca"}, - {file = "overrides-7.3.1.tar.gz", hash = "sha256:8b97c6c1e1681b78cbc9424b138d880f0803c2254c5ebaabdde57bb6c62093f2"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] -name = "packaging" -version = "23.1" -description = "Core utilities for Python packages" +name = "nose" +version = "1.3.7" +description = "nose extends unittest to make testing easier" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = "*" files = [ - {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, - {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, + {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"}, + {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"}, + {file = "nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"}, ] [[package]] -name = "pandocfilters" -version = "1.5.0" -description = "Utilities for writing pandoc filters in python" +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.7" files = [ - {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, - {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, ] [[package]] @@ -1781,14 +999,14 @@ files = [ [[package]] name = "pathspec" -version = "0.11.1" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"}, - {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] @@ -1805,14 +1023,14 @@ files = [ [[package]] name = "pexpect" -version = "4.8.0" +version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." category = "dev" optional = false python-versions = "*" files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] [package.dependencies] @@ -1844,30 +1062,30 @@ files = [ [[package]] name = "platformdirs" -version = "3.5.1" +version = "4.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"}, - {file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"}, + {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, + {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, ] [package.extras] -docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, - {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -1893,63 +1111,21 @@ tomli = ">=1.2.2" [package.extras] poetry-plugin = ["poetry (>=1.0,<2.0)"] -[[package]] -name = "prometheus-client" -version = "0.17.0" -description = "Python client for the Prometheus monitoring system." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "prometheus_client-0.17.0-py3-none-any.whl", hash = "sha256:a77b708cf083f4d1a3fb3ce5c95b4afa32b9c521ae363354a4a910204ea095ce"}, - {file = "prometheus_client-0.17.0.tar.gz", hash = "sha256:9c3b26f1535945e85b8934fb374678d263137b78ef85f305b1156c7c881cd11b"}, -] - -[package.extras] -twisted = ["twisted"] - [[package]] name = "prompt-toolkit" -version = "3.0.38" +version = "3.0.43" description = "Library for building powerful interactive command lines in Python" category = "dev" optional = false python-versions = ">=3.7.0" files = [ - {file = "prompt_toolkit-3.0.38-py3-none-any.whl", hash = "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f"}, - {file = "prompt_toolkit-3.0.38.tar.gz", hash = "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b"}, + {file = "prompt_toolkit-3.0.43-py3-none-any.whl", hash = "sha256:a11a29cb3bf0a28a387fe5122cdb649816a957cd9261dcedf8c9f1fef33eacf6"}, + {file = "prompt_toolkit-3.0.43.tar.gz", hash = "sha256:3527b7af26106cbc65a040bcc84839a3566ec1b051bb0bfe953631e704b0ff7d"}, ] [package.dependencies] wcwidth = "*" -[[package]] -name = "psutil" -version = "5.9.5" -description = "Cross-platform lib for process and system monitoring in Python." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, - {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, - {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, - {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, - {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, - {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, - {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, - {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, - {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, - {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, - {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, -] - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] - [[package]] name = "ptyprocess" version = "0.7.0" @@ -1962,18 +1138,6 @@ files = [ {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - [[package]] name = "pydocstyle" version = "6.3.0" @@ -1994,18 +1158,19 @@ toml = ["tomli (>=1.2.3)"] [[package]] name = "pygments" -version = "2.15.1" +version = "2.17.2" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, - {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [package.extras] plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyinstaller" @@ -2038,16 +1203,21 @@ hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2023.3" +version = "2024.1" description = "Community maintained hooks for PyInstaller" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pyinstaller-hooks-contrib-2023.3.tar.gz", hash = "sha256:bb39e1038e3e0972420455e0b39cd9dce73f3d80acaf4bf2b3615fea766ff370"}, - {file = "pyinstaller_hooks_contrib-2023.3-py2.py3-none-any.whl", hash = "sha256:062ad7a1746e1cfc24d3a8c4be4e606fced3b123bda7d419f14fcf7507804b07"}, + {file = "pyinstaller-hooks-contrib-2024.1.tar.gz", hash = "sha256:51a51ea9e1ae6bd5ffa7ec45eba7579624bf4f2472ff56dba0edc186f6ed46a6"}, + {file = "pyinstaller_hooks_contrib-2024.1-py2.py3-none-any.whl", hash = "sha256:131494f9cfce190aaa66ed82e82c78b2723d1720ce64d012fbaf938f4ab01d35"}, ] +[package.dependencies] +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} +packaging = ">=22.0" +setuptools = ">=42.0.0" + [[package]] name = "pylint" version = "2.15.10" @@ -2080,20 +1250,23 @@ testutils = ["gitpython (>3)"] [[package]] name = "pymdown-extensions" -version = "10.0.1" +version = "10.4" description = "Extension pack for Python Markdown." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.0.1-py3-none-any.whl", hash = "sha256:ae66d84013c5d027ce055693e09a4628b67e9dec5bce05727e45b0918e36f274"}, - {file = "pymdown_extensions-10.0.1.tar.gz", hash = "sha256:b44e1093a43b8a975eae17b03c3a77aad4681b3b56fce60ce746dbef1944c8cb"}, + {file = "pymdown_extensions-10.4-py3-none-any.whl", hash = "sha256:cfc28d6a09d19448bcbf8eee3ce098c7d17ff99f7bd3069db4819af181212037"}, + {file = "pymdown_extensions-10.4.tar.gz", hash = "sha256:bc46f11749ecd4d6b71cf62396104b4a200bad3498cb0f5dad1b8502fe461a35"}, ] [package.dependencies] markdown = ">=3.2" pyyaml = "*" +[package.extras] +extra = ["pygments (>=2.12)"] + [[package]] name = "pync" version = "2.0.3" @@ -2108,53 +1281,16 @@ files = [ [package.dependencies] python-dateutil = ">=2.0" -[[package]] -name = "pyrsistent" -version = "0.19.3" -description = "Persistent/Functional/Immutable data structures" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyrsistent-0.19.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64"}, - {file = "pyrsistent-0.19.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win32.whl", hash = "sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a"}, - {file = "pyrsistent-0.19.3-cp310-cp310-win_amd64.whl", hash = "sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da"}, - {file = "pyrsistent-0.19.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393"}, - {file = "pyrsistent-0.19.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win32.whl", hash = "sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3"}, - {file = "pyrsistent-0.19.3-cp311-cp311-win_amd64.whl", hash = "sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win32.whl", hash = "sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1"}, - {file = "pyrsistent-0.19.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b"}, - {file = "pyrsistent-0.19.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a"}, - {file = "pyrsistent-0.19.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win32.whl", hash = "sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c"}, - {file = "pyrsistent-0.19.3-cp38-cp38-win_amd64.whl", hash = "sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7"}, - {file = "pyrsistent-0.19.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win32.whl", hash = "sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2"}, - {file = "pyrsistent-0.19.3-cp39-cp39-win_amd64.whl", hash = "sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98"}, - {file = "pyrsistent-0.19.3-py3-none-any.whl", hash = "sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64"}, - {file = "pyrsistent-0.19.3.tar.gz", hash = "sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440"}, -] - [[package]] name = "pytest" -version = "7.3.1" +version = "7.4.4" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, - {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -2166,7 +1302,7 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" @@ -2189,18 +1325,18 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-describe" -version = "2.1.0" +version = "2.2.0" description = "Describe-style plugin for pytest" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-describe-2.1.0.tar.gz", hash = "sha256:0630c95ac4942ab8dcd8e766236f86436b4984896db0c059fc234fef66fe9732"}, - {file = "pytest_describe-2.1.0-py3-none-any.whl", hash = "sha256:3ea587839363a91ea24e35e442dae46b56bd91d670e63b755e002b0adfc7a7b2"}, + {file = "pytest-describe-2.2.0.tar.gz", hash = "sha256:39bb05eb90f2497d9ca342ef9a0b7fa5bada7e58505aec33f66d661d631955b7"}, + {file = "pytest_describe-2.2.0-py3-none-any.whl", hash = "sha256:bd9e2c73acb4b9522a8400823d98f5b6a081667d3bfd7243a8598336896b544d"}, ] [package.dependencies] -pytest = ">=4.6,<8" +pytest = ">=4.6,<9" [[package]] name = "pytest-expecter" @@ -2243,18 +1379,6 @@ files = [ [package.dependencies] six = ">=1.5" -[[package]] -name = "python-json-logger" -version = "2.0.7" -description = "A python library adding a json log formatter" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, - {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, -] - [[package]] name = "python-termstyle" version = "0.1.10" @@ -2270,106 +1394,76 @@ files = [ [package.dependencies] setuptools = "*" -[[package]] -name = "pywin32" -version = "306" -description = "Python for Window Extensions" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, -] - [[package]] name = "pywin32-ctypes" -version = "0.2.0" -description = "" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, - {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, -] - -[[package]] -name = "pywinpty" -version = "2.0.10" -description = "Pseudo terminal support for Windows from Python." +version = "0.2.2" +description = "A (partial) reimplementation of pywin32 using ctypes/cffi" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.6" files = [ - {file = "pywinpty-2.0.10-cp310-none-win_amd64.whl", hash = "sha256:4c7d06ad10f6e92bc850a467f26d98f4f30e73d2fe5926536308c6ae0566bc16"}, - {file = "pywinpty-2.0.10-cp311-none-win_amd64.whl", hash = "sha256:7ffbd66310b83e42028fc9df7746118978d94fba8c1ebf15a7c1275fdd80b28a"}, - {file = "pywinpty-2.0.10-cp37-none-win_amd64.whl", hash = "sha256:38cb924f2778b5751ef91a75febd114776b3af0ae411bc667be45dd84fc881d3"}, - {file = "pywinpty-2.0.10-cp38-none-win_amd64.whl", hash = "sha256:902d79444b29ad1833b8d5c3c9aabdfd428f4f068504430df18074007c8c0de8"}, - {file = "pywinpty-2.0.10-cp39-none-win_amd64.whl", hash = "sha256:3c46aef80dd50979aff93de199e4a00a8ee033ba7a03cadf0a91fed45f0c39d7"}, - {file = "pywinpty-2.0.10.tar.gz", hash = "sha256:cdbb5694cf8c7242c2ecfaca35c545d31fa5d5814c3d67a4e628f803f680ebea"}, + {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, + {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, ] [[package]] name = "pyyaml" -version = "6.0" +version = "6.0.1" description = "YAML parser and emitter for Python" category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, - {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, - {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, - {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, - {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, - {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, - {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, - {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, - {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, - {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, - {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, - {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, - {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, - {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, - {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, - {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, - {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, - {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, - {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, - {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, - {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, - {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, - {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, - {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, - {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, - {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] @@ -2388,139 +1482,20 @@ files = [ pyyaml = "*" [[package]] -name = "pyzmq" -version = "25.1.0" -description = "Python bindings for 0MQ" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:1a6169e69034eaa06823da6a93a7739ff38716142b3596c180363dee729d713d"}, - {file = "pyzmq-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:19d0383b1f18411d137d891cab567de9afa609b214de68b86e20173dc624c101"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1e931d9a92f628858a50f5bdffdfcf839aebe388b82f9d2ccd5d22a38a789dc"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97d984b1b2f574bc1bb58296d3c0b64b10e95e7026f8716ed6c0b86d4679843f"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:154bddda2a351161474b36dba03bf1463377ec226a13458725183e508840df89"}, - {file = "pyzmq-25.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cb6d161ae94fb35bb518b74bb06b7293299c15ba3bc099dccd6a5b7ae589aee3"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:90146ab578931e0e2826ee39d0c948d0ea72734378f1898939d18bc9c823fcf9"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:831ba20b660b39e39e5ac8603e8193f8fce1ee03a42c84ade89c36a251449d80"}, - {file = "pyzmq-25.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3a522510e3434e12aff80187144c6df556bb06fe6b9d01b2ecfbd2b5bfa5c60c"}, - {file = "pyzmq-25.1.0-cp310-cp310-win32.whl", hash = "sha256:be24a5867b8e3b9dd5c241de359a9a5217698ff616ac2daa47713ba2ebe30ad1"}, - {file = "pyzmq-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:5693dcc4f163481cf79e98cf2d7995c60e43809e325b77a7748d8024b1b7bcba"}, - {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:13bbe36da3f8aaf2b7ec12696253c0bf6ffe05f4507985a8844a1081db6ec22d"}, - {file = "pyzmq-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:69511d604368f3dc58d4be1b0bad99b61ee92b44afe1cd9b7bd8c5e34ea8248a"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a983c8694667fd76d793ada77fd36c8317e76aa66eec75be2653cef2ea72883"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:332616f95eb400492103ab9d542b69d5f0ff628b23129a4bc0a2fd48da6e4e0b"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58416db767787aedbfd57116714aad6c9ce57215ffa1c3758a52403f7c68cff5"}, - {file = "pyzmq-25.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:cad9545f5801a125f162d09ec9b724b7ad9b6440151b89645241d0120e119dcc"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d6128d431b8dfa888bf51c22a04d48bcb3d64431caf02b3cb943269f17fd2994"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b15247c49d8cbea695b321ae5478d47cffd496a2ec5ef47131a9e79ddd7e46c"}, - {file = "pyzmq-25.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:442d3efc77ca4d35bee3547a8e08e8d4bb88dadb54a8377014938ba98d2e074a"}, - {file = "pyzmq-25.1.0-cp311-cp311-win32.whl", hash = "sha256:65346f507a815a731092421d0d7d60ed551a80d9b75e8b684307d435a5597425"}, - {file = "pyzmq-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:8b45d722046fea5a5694cba5d86f21f78f0052b40a4bbbbf60128ac55bfcc7b6"}, - {file = "pyzmq-25.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f45808eda8b1d71308c5416ef3abe958f033fdbb356984fabbfc7887bed76b3f"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b697774ea8273e3c0460cf0bba16cd85ca6c46dfe8b303211816d68c492e132"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b324fa769577fc2c8f5efcd429cef5acbc17d63fe15ed16d6dcbac2c5eb00849"}, - {file = "pyzmq-25.1.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:5873d6a60b778848ce23b6c0ac26c39e48969823882f607516b91fb323ce80e5"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f0d9e7ba6a815a12c8575ba7887da4b72483e4cfc57179af10c9b937f3f9308f"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:414b8beec76521358b49170db7b9967d6974bdfc3297f47f7d23edec37329b00"}, - {file = "pyzmq-25.1.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:01f06f33e12497dca86353c354461f75275a5ad9eaea181ac0dc1662da8074fa"}, - {file = "pyzmq-25.1.0-cp36-cp36m-win32.whl", hash = "sha256:b5a07c4f29bf7cb0164664ef87e4aa25435dcc1f818d29842118b0ac1eb8e2b5"}, - {file = "pyzmq-25.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:968b0c737797c1809ec602e082cb63e9824ff2329275336bb88bd71591e94a90"}, - {file = "pyzmq-25.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47b915ba666c51391836d7ed9a745926b22c434efa76c119f77bcffa64d2c50c"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5af31493663cf76dd36b00dafbc839e83bbca8a0662931e11816d75f36155897"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5489738a692bc7ee9a0a7765979c8a572520d616d12d949eaffc6e061b82b4d1"}, - {file = "pyzmq-25.1.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1fc56a0221bdf67cfa94ef2d6ce5513a3d209c3dfd21fed4d4e87eca1822e3a3"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:75217e83faea9edbc29516fc90c817bc40c6b21a5771ecb53e868e45594826b0"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3830be8826639d801de9053cf86350ed6742c4321ba4236e4b5568528d7bfed7"}, - {file = "pyzmq-25.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3575699d7fd7c9b2108bc1c6128641a9a825a58577775ada26c02eb29e09c517"}, - {file = "pyzmq-25.1.0-cp37-cp37m-win32.whl", hash = "sha256:95bd3a998d8c68b76679f6b18f520904af5204f089beebb7b0301d97704634dd"}, - {file = "pyzmq-25.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:dbc466744a2db4b7ca05589f21ae1a35066afada2f803f92369f5877c100ef62"}, - {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:3bed53f7218490c68f0e82a29c92335daa9606216e51c64f37b48eb78f1281f4"}, - {file = "pyzmq-25.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eb52e826d16c09ef87132c6e360e1879c984f19a4f62d8a935345deac43f3c12"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ddbef8b53cd16467fdbfa92a712eae46dd066aa19780681a2ce266e88fbc7165"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9301cf1d7fc1ddf668d0abbe3e227fc9ab15bc036a31c247276012abb921b5ff"}, - {file = "pyzmq-25.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e23a8c3b6c06de40bdb9e06288180d630b562db8ac199e8cc535af81f90e64b"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4a82faae00d1eed4809c2f18b37f15ce39a10a1c58fe48b60ad02875d6e13d80"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c8398a1b1951aaa330269c35335ae69744be166e67e0ebd9869bdc09426f3871"}, - {file = "pyzmq-25.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d40682ac60b2a613d36d8d3a0cd14fbdf8e7e0618fbb40aa9fa7b796c9081584"}, - {file = "pyzmq-25.1.0-cp38-cp38-win32.whl", hash = "sha256:33d5c8391a34d56224bccf74f458d82fc6e24b3213fc68165c98b708c7a69325"}, - {file = "pyzmq-25.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c66b7ff2527e18554030319b1376d81560ca0742c6e0b17ff1ee96624a5f1afd"}, - {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:af56229ea6527a849ac9fb154a059d7e32e77a8cba27e3e62a1e38d8808cb1a5"}, - {file = "pyzmq-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bdca18b94c404af6ae5533cd1bc310c4931f7ac97c148bbfd2cd4bdd62b96253"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b6b42f7055bbc562f63f3df3b63e3dd1ebe9727ff0f124c3aa7bcea7b3a00f9"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c2fc7aad520a97d64ffc98190fce6b64152bde57a10c704b337082679e74f67"}, - {file = "pyzmq-25.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86a26415a8b6af02cd8d782e3a9ae3872140a057f1cadf0133de685185c02b"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:851fb2fe14036cfc1960d806628b80276af5424db09fe5c91c726890c8e6d943"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2a21fec5c3cea45421a19ccbe6250c82f97af4175bc09de4d6dd78fb0cb4c200"}, - {file = "pyzmq-25.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bad172aba822444b32eae54c2d5ab18cd7dee9814fd5c7ed026603b8cae2d05f"}, - {file = "pyzmq-25.1.0-cp39-cp39-win32.whl", hash = "sha256:4d67609b37204acad3d566bb7391e0ecc25ef8bae22ff72ebe2ad7ffb7847158"}, - {file = "pyzmq-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:71c7b5896e40720d30cd77a81e62b433b981005bbff0cb2f739e0f8d059b5d99"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cb27ef9d3bdc0c195b2dc54fcb8720e18b741624686a81942e14c8b67cc61a6"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c4fc2741e0513b5d5a12fe200d6785bbcc621f6f2278893a9ca7bed7f2efb7d"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fc34fdd458ff77a2a00e3c86f899911f6f269d393ca5675842a6e92eea565bae"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8751f9c1442624da391bbd92bd4b072def6d7702a9390e4479f45c182392ff78"}, - {file = "pyzmq-25.1.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:6581e886aec3135964a302a0f5eb68f964869b9efd1dbafdebceaaf2934f8a68"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5482f08d2c3c42b920e8771ae8932fbaa0a67dff925fc476996ddd8155a170f3"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7fbcafa3ea16d1de1f213c226005fea21ee16ed56134b75b2dede5a2129e62"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:adecf6d02b1beab8d7c04bc36f22bb0e4c65a35eb0b4750b91693631d4081c70"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6d39e42a0aa888122d1beb8ec0d4ddfb6c6b45aecb5ba4013c27e2f28657765"}, - {file = "pyzmq-25.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7018289b402ebf2b2c06992813523de61d4ce17bd514c4339d8f27a6f6809492"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9e68ae9864d260b18f311b68d29134d8776d82e7f5d75ce898b40a88df9db30f"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e21cc00e4debe8f54c3ed7b9fcca540f46eee12762a9fa56feb8512fd9057161"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f666ae327a6899ff560d741681fdcdf4506f990595201ed39b44278c471ad98"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f5efcc29056dfe95e9c9db0dfbb12b62db9c4ad302f812931b6d21dd04a9119"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:48e5e59e77c1a83162ab3c163fc01cd2eebc5b34560341a67421b09be0891287"}, - {file = "pyzmq-25.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:108c96ebbd573d929740d66e4c3d1bdf31d5cde003b8dc7811a3c8c5b0fc173b"}, - {file = "pyzmq-25.1.0.tar.gz", hash = "sha256:80c41023465d36280e801564a69cbfce8ae85ff79b080e1913f6e90481fb8957"}, -] - -[package.dependencies] -cffi = {version = "*", markers = "implementation_name == \"pypy\""} - -[[package]] -name = "qtconsole" -version = "5.4.3" -description = "Jupyter Qt console" -category = "dev" -optional = false -python-versions = ">= 3.7" -files = [ - {file = "qtconsole-5.4.3-py3-none-any.whl", hash = "sha256:35fd6e87b1f6d1fd41801b07e69339f8982e76afd4fa8ef35595bc6036717189"}, - {file = "qtconsole-5.4.3.tar.gz", hash = "sha256:5e4082a86a201796b2a5cfd4298352d22b158b51b57736531824715fc2a979dd"}, -] - -[package.dependencies] -ipykernel = ">=4.1" -ipython-genutils = "*" -jupyter-client = ">=4.1" -jupyter-core = "*" -packaging = "*" -pygments = "*" -pyzmq = ">=17.1" -qtpy = ">=2.0.1" -traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" - -[package.extras] -doc = ["Sphinx (>=1.3)"] -test = ["flaky", "pytest", "pytest-qt"] - -[[package]] -name = "qtpy" -version = "2.3.1" -description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." -category = "dev" +name = "referencing" +version = "0.33.0" +description = "JSON Referencing + Python" +category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "QtPy-2.3.1-py3-none-any.whl", hash = "sha256:5193d20e0b16e4d9d3bc2c642d04d9f4e2c892590bd1b9c92bfe38a95d5a2e12"}, - {file = "QtPy-2.3.1.tar.gz", hash = "sha256:a8c74982d6d172ce124d80cafd39653df78989683f760f2281ba91a6e7b9de8b"}, + {file = "referencing-0.33.0-py3-none-any.whl", hash = "sha256:39240f2ecc770258f28b642dd47fd74bc8b02484de54e1882b74b35ebd779bd5"}, + {file = "referencing-0.33.0.tar.gz", hash = "sha256:c775fedf74bc0f9189c2a3be1c12fd03e8c23f4d371dce795df44e06c5b412f7"}, ] [package.dependencies] -packaging = "*" - -[package.extras] -test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" [[package]] name = "requests" @@ -2545,65 +1520,130 @@ socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] -name = "rfc3339-validator" -version = "0.1.4" -description = "A pure python RFC3339 validator" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, - {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "rfc3986-validator" -version = "0.1.1" -description = "Pure python rfc3986 validator" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, - {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, -] - -[[package]] -name = "send2trash" -version = "1.8.2" -description = "Send file to trash natively under Mac OS X, Windows and Linux" -category = "dev" +name = "rpds-py" +version = "0.18.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "Send2Trash-1.8.2-py3-none-any.whl", hash = "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679"}, - {file = "Send2Trash-1.8.2.tar.gz", hash = "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"}, + {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"}, + {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"}, + {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"}, + {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"}, + {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"}, + {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"}, + {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"}, + {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"}, + {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"}, + {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"}, + {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"}, + {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"}, + {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"}, + {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"}, + {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"}, + {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"}, + {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"}, + {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"}, + {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"}, + {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"}, + {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"}, + {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"}, + {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"}, + {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"}, + {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"}, + {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"}, + {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"}, + {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"}, + {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"}, ] -[package.extras] -nativelib = ["pyobjc-framework-Cocoa", "pywin32"] -objc = ["pyobjc-framework-Cocoa"] -win32 = ["pywin32"] - [[package]] name = "setuptools" -version = "67.8.0" +version = "69.1.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, - {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, + {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, + {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "six" @@ -2640,18 +1680,6 @@ libnotify = ["py-notify (==0.3.1)"] linux = ["pyinotify (==0.9.0)"] osx = ["MacFSEvents (==0.2.8)"] -[[package]] -name = "sniffio" -version = "1.3.0" -description = "Sniff out which async library your code is running under" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, - {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, -] - [[package]] name = "snowballstemmer" version = "2.2.0" @@ -2664,58 +1692,6 @@ files = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] -[[package]] -name = "soupsieve" -version = "2.4.1" -description = "A modern CSS selector implementation for Beautiful Soup." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "soupsieve-2.4.1-py3-none-any.whl", hash = "sha256:1c1bfee6819544a3447586c889157365a27e10d88cde3ad3da0cf0ddf646feb8"}, - {file = "soupsieve-2.4.1.tar.gz", hash = "sha256:89d12b2d5dfcd2c9e8c22326da9d9aa9cb3dfab0a83a024f05704076ee8d35ea"}, -] - -[[package]] -name = "terminado" -version = "0.17.1" -description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, - {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, -] - -[package.dependencies] -ptyprocess = {version = "*", markers = "os_name != \"nt\""} -pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} -tornado = ">=6.1.0" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] - -[[package]] -name = "tinycss2" -version = "1.2.1" -description = "A tiny CSS parser" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, - {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, -] - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] - [[package]] name = "tomli" version = "2.0.1" @@ -2730,63 +1706,54 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.8" +version = "0.12.3" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "tornado" -version = "6.3.2" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "dev" -optional = false -python-versions = ">= 3.8" -files = [ - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"}, - {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"}, - {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"}, - {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"}, - {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"}, - {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"}, - {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"}, + {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, + {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] [[package]] name = "traitlets" -version = "5.9.0" +version = "5.14.1" description = "Traitlets Python configuration system" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "traitlets-5.9.0-py3-none-any.whl", hash = "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8"}, - {file = "traitlets-5.9.0.tar.gz", hash = "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9"}, + {file = "traitlets-5.14.1-py3-none-any.whl", hash = "sha256:2e5a030e6eff91737c643231bfcf04a65b0132078dad75e4936700b213652e74"}, + {file = "traitlets-5.14.1.tar.gz", hash = "sha256:8585105b371a04b8316a43d5ce29c098575c2e477850b62b848b964f1444527e"}, ] [package.extras] docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-pyyaml" +version = "6.0.12.12" +description = "Typing stubs for PyYAML" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"}, + {file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"}, +] [[package]] name = "types-requests" -version = "2.31.0.1" +version = "2.31.0.6" description = "Typing stubs for requests" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" files = [ - {file = "types-requests-2.31.0.1.tar.gz", hash = "sha256:3de667cffa123ce698591de0ad7db034a5317457a596eb0b4944e5a9d9e8d1ac"}, - {file = "types_requests-2.31.0.1-py3-none-any.whl", hash = "sha256:afb06ef8f25ba83d59a1d424bd7a5a939082f94b94e90ab5e6116bd2559deaa3"}, + {file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"}, + {file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"}, ] [package.dependencies] @@ -2794,57 +1761,42 @@ types-urllib3 = "*" [[package]] name = "types-urllib3" -version = "1.26.25.13" +version = "1.26.25.14" description = "Typing stubs for urllib3" category = "main" optional = false python-versions = "*" files = [ - {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"}, - {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"}, + {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, + {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, ] [[package]] name = "typing-extensions" -version = "4.6.3" -description = "Backported and Experimental Type Hints for Python 3.7+" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "typing_extensions-4.6.3-py3-none-any.whl", hash = "sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26"}, - {file = "typing_extensions-4.6.3.tar.gz", hash = "sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5"}, -] - -[[package]] -name = "uri-template" -version = "1.3.0" -description = "RFC 6570 URI Template Processor" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, - {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] -[package.extras] -dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] - [[package]] name = "urllib3" -version = "1.26.16" +version = "1.26.18" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, - {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, + {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, + {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] @@ -2867,39 +1819,41 @@ test = ["flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)"] [[package]] name = "watchdog" -version = "3.0.0" +version = "4.0.0" description = "Filesystem events monitoring" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, - {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, - {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, - {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, - {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, - {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, - {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, - {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, - {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, + {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"}, + {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"}, + {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"}, + {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"}, + {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"}, + {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"}, + {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"}, + {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"}, + {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"}, + {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"}, + {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"}, + {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"}, + {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"}, + {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"}, + {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"}, + {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"}, + {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"}, + {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"}, + {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"}, + {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"}, + {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"}, + {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"}, + {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"}, ] [package.extras] @@ -2907,175 +1861,113 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "wcwidth" -version = "0.2.6" +version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" category = "dev" optional = false python-versions = "*" files = [ - {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, - {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, -] - -[[package]] -name = "webcolors" -version = "1.13" -description = "A library for working with the color formats defined by HTML and CSS." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "webcolors-1.13-py3-none-any.whl", hash = "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf"}, - {file = "webcolors-1.13.tar.gz", hash = "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a"}, -] - -[package.extras] -docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] -tests = ["pytest", "pytest-cov"] - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "websocket-client" -version = "1.6.1" -description = "WebSocket client for Python with low level API options" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "websocket-client-1.6.1.tar.gz", hash = "sha256:c951af98631d24f8df89ab1019fc365f2227c0892f12fd150e935607c79dd0dd"}, - {file = "websocket_client-1.6.1-py3-none-any.whl", hash = "sha256:f1f9f2ad5291f0225a49efad77abf9e700b6fef553900623060dad6e26503b9d"}, -] - -[package.extras] -docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - -[[package]] -name = "widgetsnbextension" -version = "4.0.7" -description = "Jupyter interactive widgets for Jupyter Notebook" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "widgetsnbextension-4.0.7-py3-none-any.whl", hash = "sha256:be3228a73bbab189a16be2d4a3cd89ecbd4e31948bfdc64edac17dcdee3cd99c"}, - {file = "widgetsnbextension-4.0.7.tar.gz", hash = "sha256:ea67c17a7cd4ae358f8f46c3b304c40698bc0423732e3f273321ee141232c8be"}, + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] [[package]] name = "wrapt" -version = "1.15.0" +version = "1.16.0" description = "Module for decorators, wrappers and monkey patching." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -files = [ - {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, - {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, - {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, - {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, - {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, - {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, - {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, - {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, - {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, - {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, - {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, - {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, - {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, - {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, - {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, - {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, - {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, - {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, - {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, - {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, - {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, - {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, - {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, - {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, - {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, - {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, - {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, - {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, - {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, - {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, - {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, - {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, - {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, - {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, - {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, - {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, - {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, - {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, ] [[package]] name = "zipp" -version = "3.15.0" +version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, - {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "8c2aa180a42bfead9524d1d9383529e884d3b51fe0ff22c2687fe211a21000b3" +content-hash = "e02ead0df55978a122c91a16542813cb5cbc9fed6e5105a3ba998aa38ef3c6d4" diff --git a/pyfairdatatools/assets/datatype_dictionary.yaml b/pyfairdatatools/assets/datatype_dictionary.yaml new file mode 100644 index 0000000..d483e1a --- /dev/null +++ b/pyfairdatatools/assets/datatype_dictionary.yaml @@ -0,0 +1,142 @@ +datatype_dictionary: + - code_name: clinical_data + datatype_description: + description_text: All clinical data (survey responses, blood/urine test results, etc.). Typically collected through REDCap. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - redcap_data + related_terms: + - ncit:C15783 + related_standards: + - full_name: The Observational Medical Outcomes Partnership (OMOP) Common Data Model (CDM) + reference: https://www.ohdsi.org/data-standardization/ + standard_description: Data standard designed to standardize the structure and content of observational data and to enable efficient analyses that can produce reliable evidence. + + - code_name: ekg + datatype_description: + description_text: Recording of the moment-to-moment electromotive forces of the heart as projected onto various sites on the body's surface, delineated as a scalar function of time. The recording is monitored by a tracing on slow moving chart paper or by observing it on a cardioscope, which is a cathode ray tube display. + source: + link: https://meshb.nlm.nih.gov/record/ui?ui=D004562 + aliases: + - ecg + - electrocardiogram + - electrocardiography + - ekg_data + - ecg_data + - electrocardiogram_data + - electrocardiography_data + - ekg_measurements + - ecg_measurements + - electrocardiogram_measurements + - electrocardiography_measurements + related_terms: + - mesh:D004562 + - ncit:C168186 + + - code_name: eye_fundus_photography + datatype_description: + description_text: Data collected using a fundus camera to record color images of the condition of the interior surface of the eye. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - eye_fundus_photography_data + - eye_fundus_photography_images + - color_fundus_retinal_photography + - color_fundus_retinal_photography_data + - color_fundus_retinal_photography_images + related_terms: + - ncit:C147467 + + - code_name: oct + datatype_description: + description_text: Data collected using optical coherence tomography (OCT), an imaging method using lasers that is used for mapping subsurface structure. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - optical_coherence_tomography + - oct_data + - optical_coherence_tomography_data + - oct_images + - optical_coherence tomography_images + related_terms: + - mesh:D041623 + - ncit:C20828 + related_standards: + - full_name: Digital Imaging and Communications in Medicine (DICOM) + reference: https://dicom.nema.org/medical/dicom/2020b/output/chtml/part03/sect_C.8.17.14.html + standard_description: Standard for the digital storage and transmission of medical images and related information + + - code_name: octa + datatype_description: + description_text: Data collected using optical coherence tomography angiography (OCTA), a non-invasive imaging technique that generates volumetric angiography images. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - optical_coherence_tomography_angiography + - octa_data + - optical_coherence_tomography_angiography_data + - octa_images + - optical_coherence tomography_angiography_images + related_standards: + - full_name: Digital Imaging and Communications in Medicine (DICOM) + reference: https://www.dicomstandard.org/news/supplements/view/ophthalmic-tomography-angiographic-(oct-a)-image-storage-sop-classes + standard_description: Standard for the digital storage and transmission of medical images and related information + + - code_name: flio + datatype_description: + description_text: Data collected through fluorescence lifetime imaging ophthalmoscopy (FLIO), an imaging modality for in vivo measurement of lifetimes of endogenous retinal fluorophores. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - flio_data + - flio_images + - fluorescence_lifetime_imaging_ophthalmoscopy_data + - fluorescence_lifetime_imaging_ophthalmoscopy_images + + - code_name: continuous_glucose_monitoring + datatype_description: + description_text: Data collected through continuous glucose monitoring device. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - continuous_glucose_monitoring_data + - continuous_glucose_monitoring_measurements + related_terms: + - ncit:C159776 + + - code_name: activity_monitoring + datatype_description: + description_text: Data collected through an activity monitoring device such as Fitbit, Apple Watch, etc. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - phyisical_activity_monitoring + - activity_monitoring_data + - phyisical_activity_monitoring_data + - activity_monitoring_measurements + - phyisical_activity_monitoring_measurements + + - code_name: environmental_sensor_measurements + datatype_description: + description_text: Data collected through environmental sensor device. Typically measures of air quality, light intensity, etc. + description_source: + organization: + full_name: AI-READI Consortium + link: https://aireadi.org/ + aliases: + - environmental_sensor_measurements_data \ No newline at end of file diff --git a/pyfairdatatools/cfpir.py b/pyfairdatatools/cfpir.py new file mode 100644 index 0000000..5ac3047 --- /dev/null +++ b/pyfairdatatools/cfpir.py @@ -0,0 +1,45 @@ +import sys + +from cfpir_converter import convert_zip_dicom +from cfpir_metadata_extract import save_dicom_info_as_tsv +from standards import DataDomain + + +class cfpir(DataDomain): + """ + Custom data domain class for CFP/IR DICOM data. + + This class inherits from the DataDomain class and defines methods to convert and extract + metadata from CFP/IR DICOM data files. + + Inherits: + DataDomain (class): Base class for data domain implementation. + + Methods: + convert(infile, outfile): Converts a CFP/IR DICOM file to the right format. + metadata(files, outfile): Extracts metadata from CFP/IR DICOM files and saves it as a TSV file. + """ + + def __init__(self): + super().__init__() + + def convert(self, infile, outfile): + """ + Convert a CFP/IR DICOM file to the right format. + + Args: + infile (str): Path to the input CFP/IR DICOM file. + outfile (str): Path to the output converted file. + """ + + convert_zip_dicom(infile, outfile) + + def metadata(self, files, outfile): + """ + Extract metadata from CFP/IR DICOM files and save as a TSV file. + + Args: + files (list): List of paths to input CFP/IR DICOM files. + outfile (str): Path to the output TSV file. + """ + save_dicom_info_as_tsv(files, outfile) diff --git a/pyfairdatatools/cfpir_converter.py b/pyfairdatatools/cfpir_converter.py new file mode 100644 index 0000000..0375631 --- /dev/null +++ b/pyfairdatatools/cfpir_converter.py @@ -0,0 +1,543 @@ +import os +import shutil +import tempfile +import zipfile + +import pydicom + +KEEP = 0 +BLANK = 1 +HARMONIZE = 2 + + +class ConversionRule: + """ + Represents a conversion rule for processing data. + + This class defines a rule used for data conversion and processing. It contains attributes + such as the rule's name, header elements, individual elements, and sequences of elements. + + Attributes: + name (str): The name of the conversion rule. + header_elements (list): List of Element instances representing header elements. + elements (list): List of Element instances representing individual elements. + sequences (list): List of Sequence instances representing sequences of elements. + + Methods: + header_tags(): Extracts unique tags from header elements. + tags(): Extracts unique tags from individual elements. + sequence_tags(): Generates a dictionary of sequence tags and associated element tags. + + """ + + def __init__(self, name, headers, elements, sequences): + self.name = name + self.header_elements = headers + self.elements = elements + self.sequences = sequences + + def header_tags(self): + headertags = set() + for header_element in self.header_elements: + headertags.add(header_element.tag) + + return list(headertags) + + def tags(self): + tags = set() + for element in self.elements: + tags.add(element.tag) + + return list(tags) + + def sequence_tags(self): + tags_dict = {} + for sequence in self.sequences: + element_tags = [element.tag for element in sequence.elements] + tags_dict[sequence.tag] = element_tags + + return tags_dict + + +class Element: + """ + Represents an individual data element. + + This class defines an individual data element with attributes such as its name, tag, + value representation (vr), decision, and harmonized value. + + Attributes: + name (str): The name of the data element. + tag (str): The tag associated with the data element. + vr (str): The value representation of the data element. + decision (int): The decision related to the data element (default is 0). + harmonized_value (int): The harmonized value of the data element (default is 0). + """ + + def __init__(self, name, tag, vr, decision=0, harmonized_value=0): + self.name = name + self.tag = tag + self.vr = vr + self.decision = decision + self.harmonized_value = harmonized_value + + +class ElementList: + """ + Represents a list of related data elements. + + This class defines a list of related data elements with attributes such as its name, + tag, value representation (vr), and the list of elements. + + Attributes: + name (str): The name of the element list. + tag (str): The tag associated with the element list. + vr (str): The value representation of the element list. + elements (list): List of Element instances representing the data elements in the list (default is an empty list). + """ + + def __init__(self, name, tag, vr, elements=None): + self.name = name + self.tag = tag + self.vr = vr + self.elements = elements if elements is not None else [] + + +cfp_ir = ConversionRule( + "CFP IR", + # DICOM header elements + headers=[ + Element("FileMetaInformationGroupLength", "00020000", "UL"), + Element("FileMetaInformationVersion", "00020001", "OB"), + Element("MediaStorageSOPClassUID", "00020002", "UI"), + Element("MediaStorageSOPInstanceUID", "00020003", "UI"), + Element("TransferSyntaxUID", "00020010", "UI"), + Element("ImplementationClassUID", "00020012", "UI"), + Element("ImplementationVersionName", "00020013", "SH"), + ], + # DICOM elements + elements=[ + Element("PatientName", "00100010", "PN", BLANK), + Element("PatientID", "00100020", "LO"), + Element("PatientBirthDate", "00100030", "DA", BLANK), + Element("PatientSex", "00100040", "CS", BLANK), + Element("StudyInstanceUID", "0020000D", "UI"), + Element("StudyDate", "00080020", "DM"), + Element("StudyTime", "00080030", "TM"), + Element("ReferringPhysicianName", "00080090", "PN", BLANK), + Element("StudyID", "00200010", "SH", BLANK), + Element("AccessionNumber", "00080050", "SH", BLANK), + Element("StudyDescription", "00081030", "LO", HARMONIZE, "CFP/IR"), + Element("Modality", "00080060", "CS"), + Element("SeriesInstanceUID", "0020000E", "UI"), + Element("SeriesNumber", "00200011", "IS"), + Element("SynchronizationFrameOfReferenceUID", "00200200", "UI"), + Element("SynchronizationTrigger", "0018106A", "CS"), + Element("AcquisitionTimeSynchronized", "00181800", "CS"), + Element("Manufacturer", "00080070", "LO"), + Element("ManufacturerModelName", "00081090", "LO"), + Element("DeviceSerialNumber", "00181000", "LO"), + Element("SoftwareVersions", "00181020", "LO"), + Element("InstanceNumber", "00200013", "IS"), + Element("PatientOrientation", "00200020", "CS"), + Element("BurnedInAnnotation", "00280301", "CS"), + Element("PatientEyeMovementCommanded", "00220005", "CS"), + Element("HorizontalFieldOfView", "0022000C", "FL"), + Element("DetectorType", "00187004", "CS"), + Element("Rows", "00280010", "US"), + Element("Columns", "00280011", "US"), + Element("BitsAllocated", "00280100", "US"), + Element("BitsStored", "00280101", "US"), + Element("HighBit", "00280102", "US"), + Element("PixelRepresentation", "00280103", "US"), + Element("SamplePerPixel", "00280002", "US"), + Element("PlanarConfiguration", "00280006", "US"), + Element("PhotometricInterpretation", "00280004", "CS"), + Element("NumberOfFrames", "00280008", "IS"), + Element("FrameIncrementPointer", "00280009", "AT"), + Element("ImageType", "00080008", "CS", HARMONIZE, "ORIGINAL PRIMARY"), + Element("ContentTime", "00080033", "TM"), + Element("ContentDate", "00080023", "DA"), + Element("AcquisitionDateTime", "0008002A", "DT"), + Element("LossyImageCompression", "00282110", "CS"), + Element("LossyImageCompressionRatio", "00282112", "DS"), + Element("LossyImageCompressionMethod", "00282114", "CS"), + Element("PresentationLUTShape", "20500020", "CS"), + Element("PixelSpacing", "00280030", "DS"), + Element("ImageLaterality", "00200062", "CS"), + Element("PatientEyeMovementCommanded", "00220005", "CS"), + Element("HorizontalFieldOfView", "0022000C", "FL"), + Element("DetectorType", "00187004", "CS"), + Element("SOPClassUID", "00080016", "UI"), + Element("SOPInstanceUID", "00080018", "UI"), + Element("SpecificCharacterSet", "00080005", "CS"), + ], + # DICOM sequences + sequences=[ + ElementList("LightPathFilterTypeStackCodeSequence", "00220017", "SQ"), + ElementList("ImagePathFilterTypeStackCodeSequence", "00220018", "SQ"), + ElementList( + "LensesCodeSequence", + "00220019", + "SQ", + [ + Element("CodeValue", "00080100", "SH"), + Element("CodingSchemeDesignator", "00080102", "SH"), + Element("CodeMeaning", "00080104", "LO"), + ], + ), + ElementList( + "IlluminationTypeCodeSequence", + "00220016", + "SQ", + [ + Element("CodeValue", "00080100", "SH"), + Element("CodingSchemeDesignator", "00080102", "SH"), + Element("CodeMeaning", "00080104", "LO"), + ], + ), + ElementList( + "ChannelDescriptionCodeSequence", + "0022001A", + "SQ", + [ + Element("CodeValue", "00080100", "SH"), + Element("CodingSchemeDesignator", "00080102", "SH"), + Element("CodeMeaning", "00080104", "LO"), + ], + ), + ElementList( + "PatientEyeMovementCommandCodeSequence", + "00220006", + "SQ", + [ + Element("CodeValue", "00080100", "SH"), + Element("CodingSchemeDesignator", "00080102", "SH"), + Element("CodeMeaning", "00080104", "LO"), + ], + ), + ElementList( + "AnatomicRegionSequence", + "00082218", + "SQ", + [ + Element("CodeValue", "00080100", "SH", HARMONIZE, "T-AA610"), + Element("CodingSchemeDesignator", "00080102", "SH", HARMONIZE, "SRT"), + Element("CodeMeaning", "00080104", "LO", HARMONIZE, "Retina"), + ], + ), + ElementList( + "AcquisitionDeviceTypeCodeSequence", + "00220015", + "SQ", + [ + Element("CodeValue", "00080100", "SH"), + Element("CodingSchemeDesignator", "00080102", "SH"), + Element("CodeMeaning", "00080104", "LO"), + ], + ), + ], +) + + +def process_tags(tags, dicom): + """ + Process DICOM tags and create a dictionary of DicomEntry instances. + + This function processes a list of DICOM tags from a given DICOM dictionary and constructs + a dictionary of DicomEntry instances representing the metadata associated with each tag. + + Args: + tags (list): List of DICOM tags to process. + dicom (dict): The DICOM dictionary containing the metadata. + + Returns: + dict: Dictionary where keys are DICOM tags and values are DicomEntry instances. + + """ + output = dict() + for tag in tags: + if tag in dicom: + element_name = pydicom.tag.Tag(tag) + vr = dicom[tag]["vr"] + value = dicom[tag].get( + "Value", [] + ) # Assign [] as value if "Value" key is not present + + if not value or not isinstance(value[0], dict): + output[tag] = DicomEntry(tag, element_name, vr, value) + else: + data = dicom[tag]["Value"][0] + keys_list = list(data.keys()) + nested_output = process_tags(keys_list, data) + output[tag] = DicomEntry(tag, element_name, vr, [nested_output]) + return output + + +class DicomEntry: + """ + Represents a DICOM metadata entry. + + This class encapsulates information about a single DICOM metadata entry, including its + tag, name, value representation (vr), and associated value. + + Attributes: + tag (str): The DICOM tag of the metadata entry. + name (pydicom.tag.Tag): The name (tag) associated with the metadata entry. + vr (str): The value representation of the metadata entry. + value (list): The value associated with the metadata entry. + + Methods: + is_empty(): Checks if the value of the metadata entry is empty. + + """ + + def __init__(self, tag, name, vr, value): + self.tag = tag + self.name = name + self.vr = vr + self.value = value + + def is_empty(self): + return len(self.value) == 0 + + +def extract_dicom_dict(file, tags): + """ + Extract DICOM metadata and information from a DICOM file. + + This function reads a DICOM file, extracts metadata, header elements, and specific + tags from it. It then processes the tags to create a dictionary representation of + the DICOM metadata, along with information about transfer syntax and pixel data. + + Args: + file (str): The path to the DICOM file. + tags (list): List of DICOM tags to process. + + Returns: + tuple: A tuple containing: + - dict: Dictionary representation of DICOM metadata with processed tags. + - list: List of transfer syntax information. + - bytes: Pixel data from the DICOM file. + + Raises: + FileNotFoundError: If the specified DICOM file does not exist. + + """ + if not os.path.exists(file): + raise FileNotFoundError(f"File {file} not found.") + + output = dict() + output["filepath"] = file + + dataset = pydicom.dcmread(file) + + header_elements = { + "00020000": { + "vr": "UL", + "Value": [dataset.file_meta.FileMetaInformationGroupLength], + }, + "00020001": { + "vr": "OB", + "Value": [dataset.file_meta.FileMetaInformationVersion], + }, + "00020002": {"vr": "UI", "Value": [dataset.file_meta.MediaStorageSOPClassUID]}, + "00020003": { + "vr": "UI", + "Value": [dataset.file_meta.MediaStorageSOPInstanceUID], + }, + "00020010": { + "vr": "UI", + "Value": [dataset.file_meta.TransferSyntaxUID], + }, + "00020012": { + "vr": "UI", + "Value": [dataset.file_meta.ImplementationClassUID], + }, + "00020013": { + "vr": "SH", + "Value": [dataset.file_meta.ImplementationVersionName], + }, + } + json_dict = {} + json_dict.update(header_elements) + info = dataset.to_json_dict() + + patient_name = dataset.PatientName + info["00100010"]["Value"] = [patient_name] + + physician_name = dataset.ReferringPhysicianName + info["00080090"]["Value"] = [physician_name] + + json_dict.update(info) + + dicom = json_dict + + output = process_tags(tags, dicom) + + transfersyntax = [dataset.is_little_endian, dataset.is_implicit_VR] + pixeldata = dataset.PixelData + + return output, transfersyntax, pixeldata + + +def write_dicom(protocol, dicom_dict_list, file_path): + """ + Write DICOM data to a new DICOM file. + + This function takes a protocol, a list of DICOM dictionaries, and a file path. It constructs + a new DICOM dataset using the provided protocol and DICOM dictionaries. The dataset is then + written to a new DICOM file at the specified path. + + Args: + protocol (ConversionRule): The ConversionRule instance containing processing instructions. + dicom_dict_list (list): List containing DICOM dictionaries and related information. + file_path (str): The path to the new DICOM file to be created. + + """ + headertags = protocol.header_tags() + tags = protocol.tags() + sequencetags = protocol.sequence_tags() + + file_meta = pydicom.Dataset() + + for headertag in headertags: + value = dicom_dict_list[0][headertag].value + element_name = pydicom.datadict.keyword_for_tag( + dicom_dict_list[0][headertag].tag + ) + setattr(file_meta, element_name, value) + + dataset = pydicom.Dataset() + dataset.file_meta = file_meta + + for tag in tags: + for element in protocol.elements: + if element.tag == tag: + desired_element = element + + if desired_element.decision == BLANK: + value = [] + + elif desired_element.decision == HARMONIZE: + value = [desired_element.harmonized_value] + + elif tag in dicom_dict_list[0]: + value = dicom_dict_list[0][tag].value + + else: + value = [] + + element_name = ( + pydicom.datadict.keyword_for_tag(dicom_dict_list[0][tag].tag) + if tag in dicom_dict_list[0] + else pydicom.datadict.keyword_for_tag(tag) + ) + setattr(dataset, element_name, value) + + dataset.is_little_endian = dicom_dict_list[1][0] + dataset.is_implicit_VR = dicom_dict_list[1][1] + dataset.PixelData = dicom_dict_list[2] + + if dicom_dict_list[0]["00081090"].value == ["Triton"]: + dataset.Manufacturer = ["Topcon"] + + keys = list(sequencetags.keys()) + + for key in keys: + for sequence in protocol.sequences: + if sequence.tag == key: + desired_sequence = sequence + + if key in dicom_dict_list[0]: + sequencetag = key + seq = pydicom.Sequence() + elementkeys = sequencetags[sequencetag] + + if dicom_dict_list[0][key].value: + x = dicom_dict_list[0][key].value[0] + key_list = list(x.keys()) + + item = pydicom.Dataset() + for elementkey in elementkeys: + for element in desired_sequence.elements: + if element.tag == elementkey: + desired_element = element + if elementkey in key_list and desired_element.decision == BLANK: + value = [] + elif ( + elementkey in key_list and desired_element.decision == HARMONIZE + ): + value = desired_element.harmonized_value + elif elementkey in key_list: + value = dicom_dict_list[0][key].value[0][elementkey].value + element_tag = ( + dicom_dict_list[0][sequencetag].value[0][elementkey].tag + ) + element_name = pydicom.datadict.keyword_for_tag(element_tag) + setattr(item, element_name, value) + seq.append(item) + + value = seq + element_name = pydicom.datadict.keyword_for_tag( + dicom_dict_list[0][key].tag + ) + setattr(dataset, element_name, value) + + else: + value = seq + element_name = pydicom.datadict.keyword_for_tag( + dicom_dict_list[0][key].tag + ) + setattr(dataset, element_name, value) + else: + value = pydicom.Sequence() + element_name = pydicom.datadict.keyword_for_tag(key) + setattr(dataset, element_name, value) + pydicom.filewriter.write_file(file_path, dataset, write_like_original=False) + + +def convert_dicom(input, output): + """ + Convert DICOM data from an input file to an output file using a conversion rule. + + This function facilitates the conversion of DICOM data from an input file to an output file. + It uses a specified conversion rule to process the data and writes the converted data to the + output file. + + Args: + input (str): The path to the input DICOM file. + output (str): The path to the output DICOM file to be created. + + """ + conversion_rule = cfp_ir + tags = ( + conversion_rule.header_tags() + + conversion_rule.tags() + + list(conversion_rule.sequence_tags().keys()) + ) + x = extract_dicom_dict(input, tags) + write_dicom(conversion_rule, x, output) + + +def list_files_recursive(directory): + all_files = [] + for root, _, files in os.walk(directory): + for file_name in files: + file_path = os.path.join(root, file_name) + all_files.append(file_path) + return all_files + + +def convert_zip_dicom(zip_file_path, output): + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(zip_file_path, "r") as zip_ref: + zip_ref.extractall(temp_dir) + extracted_files = list_files_recursive(temp_dir) + convert_dicom(extracted_files[0], output) + except Exception as e: + print(f"An error occurred: {str(e)}") + finally: + shutil.rmtree(temp_dir, ignore_errors=True) + return None diff --git a/pyfairdatatools/cfpir_metadata_extract.py b/pyfairdatatools/cfpir_metadata_extract.py new file mode 100644 index 0000000..87b1c72 --- /dev/null +++ b/pyfairdatatools/cfpir_metadata_extract.py @@ -0,0 +1,52 @@ +import csv +import os + +import pydicom + + +def save_dicom_info_as_tsv(files, output_file): + """ + Save DICOM metadata information as a TSV file. + + This function takes a list of DICOM files and saves selected metadata information from each file + into a Tab-Separated Values (TSV) file. The saved information includes domain, modality, patient ID, + laterality, manufacturer, file path, and acquisition datetime. + + Args: + files (list): List of paths to the input DICOM files. + output_file (str): The path to the output TSV file to be created. + + """ + with open(output_file, "w", newline="") as tsv_file: + writer = csv.writer(tsv_file, delimiter="\t") + writer.writerow( + [ + "domain", + "modality", + "patient_id", + "laterality", + "manufacturer", + "filepath", + "acquisitiondatetime", + ] + ) + + for file in files: + data_dict = {} + try: + dicom = pydicom.dcmread(file) + data_dict["domain"] = "DICOM" + data_dict["modality"] = dicom.Modality + if dicom.SOPClassUID == "1.2.840.10008.5.1.4.1.1.77.1.5.1": + data_dict["modality"] = "CFP/IR" + else: + data_dict["modality"] = "not CFP/IR" + data_dict["patient_id"] = dicom.PatientID + data_dict["laterality"] = dicom.ImageLaterality + data_dict["manufacturer"] = dicom.Manufacturer + data_dict["filepath"] = os.path.abspath(file) + data_dict["acquisitiondatetime"] = dicom.AcquisitionDateTime + except pydicom.errors.InvalidDicomError: + data_dict["domain"] = "Not DICOM" + + writer.writerow(data_dict.values()) diff --git a/pyfairdatatools/classifying_rules.py b/pyfairdatatools/classifying_rules.py new file mode 100644 index 0000000..4c7c2a6 --- /dev/null +++ b/pyfairdatatools/classifying_rules.py @@ -0,0 +1,552 @@ +# type: ignore + +import os +import shutil +import tempfile +import zipfile + +import pydicom +import xmltodict +from defusedxml import minidom + + +class ClassifyingRule: + def __init__(self, name, conditions): + self.name = name + self.conditions = conditions + + def apply(self, dicom_entry): + for condition in self.conditions: + if not condition(dicom_entry): + return False + return True + + +# List of ClassifyingRule instances +rules = [ + # optomed + ClassifyingRule( + "OptoMed_CFP_Disc_or_Mac_centered", + conditions=[lambda entry: "Aurora" == entry.device], + ), + # eidon + ClassifyingRule( + "Eidon_UWF_Central_IR", + conditions=[ + lambda entry: "0-infrared" in entry.filename.lower() + and "Eidon" in entry.device + ], + ), + ClassifyingRule( + "Eidon_UWF_Central_FAF", + conditions=[ + lambda entry: "0-af-" in entry.filename.lower() and "Eidon" in entry.device + ], + ), + ClassifyingRule( + "Eidon_UWF_Central_CFP", + conditions=[ + lambda entry: "0-visible" in entry.filename.lower() + and "Eidon" in entry.device + ], + ), + ClassifyingRule( + "Eidon_UWF_Nasal_CFP", + conditions=[ + lambda entry: "3-visible" in entry.filename.lower() + and "Eidon" in entry.device + ], + ), + ClassifyingRule( + "Eidon_UWF_Temporal_CFP", + conditions=[ + lambda entry: "4-visible" in entry.filename.lower() + and "Eidon" in entry.device + ], + ), + ClassifyingRule( + "Eidon_UWF_Mosaic_CFP", + conditions=[ + lambda entry: "11-visible" in entry.filename.lower() + and "Eidon" in entry.device + ], + ), + # maestro + ClassifyingRule( + "Maestro2_3D_Wide_OCT", + conditions=[ + lambda entry: "3DOCT-1Maestro2" == entry.device + and "1.2.840.10008.5.1.4.1.1.77.1.5.4" == entry.sopclassuid + and str(entry.slicethickness).startswith("0.07") + ], + ), + ClassifyingRule( + "Maestro2_3D_Macula_OCT", + conditions=[ + lambda entry: "3DOCT-1Maestro2" == entry.device + and "1.2.840.10008.5.1.4.1.1.77.1.5.4" == entry.sopclassuid + and str(entry.slicethickness).startswith("0.04") + ], + ), + ClassifyingRule( + "Maestro2_Mac_6x6-360x360_OCTA", + conditions=[ + lambda entry: entry.device == "3DOCT-1Maestro2" + and "fo-dicom 4.0.8" == entry.implementationversion + and str(entry.slicethickness).startswith("0.01") + and "1.2.840.10008.5.1.4.1.1.77.1.5.4" == entry.sopclassuid + and entry.filename.endswith(".1.1.dcm") + ], + ), + # triton + ClassifyingRule( + "Triton_3D(H)_Radial_OCT", + conditions=[ + lambda entry: "fo-dicom 4.0.8" == entry.implementationversion + and "1.2.840.10008.5.1.4.1.1.77.1.5.4" == entry.sopclassuid + and str(entry.slicethickness).startswith("0.03") + and "Triton plus" == entry.device + ], + ), + ClassifyingRule( + "Triton_Macula_6*6_OCTA", + conditions=[ + lambda entry: entry.device == "Triton plus" + and str(entry.slicethickness).startswith("0.01") + and "fo-dicom 4.0.8" == entry.implementationversion + and entry.filename.endswith(".1.1.dcm") + ], + ), + ClassifyingRule( + "Triton_Macula_12*12_OCTA", + conditions=[ + lambda entry: entry.device == "Triton plus" + and str(entry.slicethickness).startswith("0.02") + and "fo-dicom 4.0.8" == entry.implementationversion + and entry.filename.endswith(".1.1.dcm") + ], + ), + # #spectralis + ClassifyingRule( + "Spec_ONH_RC_HR_OCT", + conditions=[ + lambda entry: entry.device == "Spectralis" + and (not isinstance(entry.framenumber, str)) + and (26 <= int(entry.framenumber) <= 28) + and str(entry.rows) == "496" + and str(entry.columns) == "768" + and entry.slicethickness == "" + ], + ), + ClassifyingRule( + "Spec_ONH_RC_HR_OCT_reference_IR", + conditions=[ + lambda entry: entry.device == "Spectralis" + and str(entry.rows) == "1536" + and str(entry.columns) == "1536" + ], + ), + ClassifyingRule( + "Spec_PPole_Mac_HR_OCT", + conditions=[ + lambda entry: entry.device == "Spectralis" + and (not isinstance(entry.framenumber, str)) + and (60 <= int(entry.framenumber) <= 62) + and str(entry.rows) == "496" + and str(entry.columns) == "768" + ], + ), + ClassifyingRule( + "Spec_PPole_Mac_HR_OCT_reference_IR", + conditions=[ + lambda entry: entry.device == "Spectralis" + and str(entry.rows) == "768" + and str(entry.columns) == "768" + and str(entry.privatetag) == "N/A" + and str(entry.gaze) == "R-1022D" + ], + ), + ClassifyingRule( + "Spec-Mac-20x20-HS_OCTA_reference_Bscan", + conditions=[ + lambda entry: entry.device == "Spectralis" + and (not isinstance(entry.framenumber, str)) + and (511 <= int(entry.framenumber) <= 513) + and str(entry.rows) == "496" + and str(entry.columns) == "512" + ], + ), + ClassifyingRule( + "Spec-Mac-20x20-HS_OCTA_reference_IR", + conditions=[ + lambda entry: entry.device == "Spectralis" + and str(entry.rows) == "768" + and str(entry.columns) == "768" + and str(entry.privatetag) == "Super Slim" + ], + ) + # OCTA + # FLIO +] + + +class DicomEntry: + def __init__( + self, + filename, + patientid, + sopclassuid, + sopinstanceuid, + laterality, + rows, + columns, + device, + framenumber, + referencedsopinstance, + slicethickness, + implementationversion, + gaze, + privatetag, + softwareversion, + numberoffiles, + ): + self.filename = filename + self.patientid = patientid + self.sopclassuid = sopclassuid + self.sopinstanceuid = sopinstanceuid + self.laterality = laterality + self.rows = rows + self.columns = columns + self.device = device + + self.framenumber = framenumber + self.referencedsopinstance = referencedsopinstance + self.slicethickness = slicethickness + self.implementationversion = implementationversion + self.gaze = gaze + self.privatetag = privatetag + self.softwareversion = softwareversion + self.numberoffiles = numberoffiles + + +class DicomSummary: + def __init__( + self, domain, patientid, laterality, protocol + ): # sopinstance, matchingcfpifsopinstance + self.domain = domain # DICOM + self.patientid = patientid # patient id + self.laterality = laterality # laterality + self.protocol = protocol # belongs to which one in AIREADI checklist + + +def extract_dicom_entry(file): + if not os.path.exists(file): + raise FileNotFoundError(f"File {file} not found.") + + dicom = pydicom.dcmread(file).to_json_dict() + ds = pydicom.dcmread(file) + + filename = os.path.basename(file) + patientid = dicom["00100020"]["Value"][0] + sopclassuid = dicom["00080016"]["Value"][0] + sopinstanceuid = dicom["00080018"]["Value"][0] + + folder_path = os.path.dirname(file) + folder_files = os.listdir(folder_path) + filecount = len( + [f for f in folder_files if os.path.isfile(os.path.join(folder_path, f))] + ) + + # Fundus photo 2D + if sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.1": + rows = dicom["00280010"]["Value"][0] + columns = dicom["00280011"]["Value"][0] + laterality = dicom["00200062"]["Value"][0] + implementationversion = ds.file_meta.ImplementationVersionName + device = dicom["00081090"]["Value"][0] + softwareversion = dicom["00181020"]["Value"][0] + numberoffiles = filecount + if "00511017" in dicom: + privatetag = dicom["00511017"]["Value"][0] + else: + privatetag = "N/A" + + if "00220006" in dicom and "00080100" in dicom["00220006"]["Value"][0]: + gaze = dicom["00220006"]["Value"][0]["00080100"]["Value"][0] + else: + gaze = "N/A" + + framenumber = referencedsopinstance = slicethickness = "N/A" + # B-Scan OCT + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.4": + rows = dicom["00280010"]["Value"][0] + columns = dicom["00280011"]["Value"][0] + laterality = dicom["00200062"]["Value"][0] + implementationversion = ds.file_meta.ImplementationVersionName + device = dicom["00081090"]["Value"][0] + framenumber = dicom["00280008"]["Value"][0] + softwareversion = dicom["00181020"]["Value"][0] + numberoffiles = filecount + referencedsopinstance = dicom["52009229"]["Value"][0]["00081140"]["Value"][0][ + "00081155" + ]["Value"][0] + if ( + "52009229" in dicom + and "00289110" in dicom["52009229"]["Value"][0] + and "00180050" in dicom["52009229"]["Value"][0]["00289110"]["Value"][0] + ): + slicethickness = dicom["52009229"]["Value"][0]["00289110"]["Value"][0][ + "00180050" + ]["Value"][0] + else: + slicethickness = "" + + privatetag = gaze = "N/A" + + # B-scan Volume Analysis Storage + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.8": + laterality = dicom["52009229"]["Value"][0]["00209071"]["Value"][0]["00209072"][ + "Value" + ][0] + rows = dicom["00280010"]["Value"][0] + columns = dicom["00280011"]["Value"][0] + framenumber = dicom["00280008"]["Value"][0] + device = dicom["00081090"]["Value"][0] + implementationversion = ds.file_meta.ImplementationVersionName + slicethickness = dicom["52009229"]["Value"][0]["00289110"]["Value"][0][ + "00180050" + ]["Value"][0] + referencedsopinstance = dicom["00200052"]["Value"][0] + privatetag = softwareversion = gaze = "N/A" + numberoffiles = filecount + + # segmentation + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.66.5": + laterality = dicom["00200062"]["Value"][0] + device = dicom["00081090"]["Value"][0] + referencedsopinstance = dicom["00081115"]["Value"][0]["0008114A"]["Value"][0][ + "00081155" + ]["Value"][0] + implementationversion = ds.file_meta.ImplementationVersionName + numberoffiles = filecount + rows = ( + columns + ) = framenumber = slicethickness = privatetag = gaze = softwareversion = "N/A" + + # en face + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.7": # en face + laterality = dicom["00200062"]["Value"][0] + rows = dicom["00280010"]["Value"][0] + columns = dicom["00280011"]["Value"][0] + implementationversion = ds.file_meta.ImplementationVersionName + device = dicom["00081090"]["Value"][0] + numberoffiles = filecount + referencedsopinstance = dicom["00082112"]["Value"][0]["00081155"]["Value"][0] + framenumber = slicethickness = privatetag = gaze = softwareversion = "N/A" + + # unknown + else: + sopinstanceuid = f"Unknown SOP Class UID: {sopclassuid}" + laterality = ( + device + ) = ( + rows + ) = ( + referencedsopinstance + ) = ( + implementationversion + ) = ( + columns + ) = ( + framenumber + ) = slicethickness = privatetag = gaze = numberoffiles = softwareversion = "N/A" + + output = DicomEntry( + filename, + patientid, + sopclassuid, + sopinstanceuid, + laterality, + rows, + columns, + device, + framenumber, + referencedsopinstance, + slicethickness, + implementationversion, + gaze, + privatetag, + softwareversion, + numberoffiles, + ) + return output + + +def find_rule(file): + dicomentry = extract_dicom_entry(file) + matching_rules = [rule for rule in rules if rule.apply(dicomentry)] + if matching_rules: + for rule in matching_rules: + return str(rule.name) + else: + return "No rules apply." + + +## Domain, Modality, Protocol, Patient ID, Laterlity, sopinstanceuid, referencedsopinstance +def extract_dicom_summary(file): + dicomentry = extract_dicom_entry(file) + sopclassuid = dicomentry.sopclassuid + + try: + dcm = pydicom.dcmread(file) + domain = "DICOM" + + except pydicom.errors.InvalidDicomError: + domain = "NOT DICOM" + + if sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.1": + modality = "CFP/IR/FAF" + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.4": + modality = "OCT B Scan" + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.8": + modality = "B-scan Volume Analysis Storage" + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.66.5": + modality = "Surface Segmentation Storage" + elif sopclassuid == "1.2.840.10008.5.1.4.1.1.77.1.5.7": + modality = "En Face OCTA Image" + else: + modality = sopclassuid + + sopinstanceuid = dicomentry.sopinstanceuid + device = dicomentry.device + patientid = dicomentry.patientid + laterality = dicomentry.laterality + referencedsopinstance = dicomentry.referencedsopinstance + softwareversion = dicomentry.softwareversion + numberoffiles = dicomentry.numberoffiles + protocol = find_rule(file) + + output = DicomSummary(domain, patientid, laterality, protocol) + return output + + +def get_dicom_summary(file): + dicomsummary = extract_dicom_summary(file) + obj_dict = vars(dicomsummary) + return obj_dict + + +def list_files_recursive(directory): + all_files = [] + for root, _, files in os.walk(directory): + for file_name in files: + file_path = os.path.join(root, file_name) + all_files.append(file_path) + return all_files + + +def process_dicom_zip(zip_file_path): + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(zip_file_path, "r") as zip_ref: + zip_ref.extractall(temp_dir) + extracted_files = list_files_recursive(temp_dir) + + dicom_files = [ + f for f in extracted_files if f.endswith(".dcm") and "/__" not in f + ] + + if len(dicom_files) == 1: + dicom_file_path = os.path.join(temp_dir, dicom_files[0]) + dicom = get_dicom_summary(dicom_file_path) + return dicom + + elif len(dicom_files) > 1: + for dicom_file in dicom_files: + if dicom_file.endswith(".1.1.dcm") and "/." not in dicom_file: + dicom_file_path = os.path.join(temp_dir, dicom_file) + dicom = get_dicom_summary(dicom_file_path) + return dicom + else: + print("Error: no DICOM file present in the zip archive.") + + except Exception as e: + print(f"An error occurred: {str(e)}") + finally: + shutil.rmtree(temp_dir, ignore_errors=True) + return None + + +def process_env_zip(file_path): + path_parts = file_path.split("/") + filename = path_parts[-1] + filename_parts = filename.split("-") + patient_id = "AIREADI-" + filename_parts[-2] + sensor_id = filename_parts[-1].split(".")[0] + info_dict = { + "domain": "CSV", + "patient_id": patient_id, + "laterality": "N/A", + "protocol": "environmental_sensor", + "sensor_id": sensor_id, + } + + return info_dict + + +def process_flio_zip(file_path): + path_parts = file_path.split("/") + filename = path_parts[-1] + filename_parts = filename.split("_") + patient_id = "AIREADI-" + filename_parts[-7] + laterality = filename_parts[-1][:2] + + if laterality == "OD": + laterality = "R" + + elif laterality == "OS": + laterality = "L" + else: + print("Invalid laterality") + + info_dict = { + "domain": "DICOM", + "patient_id": patient_id, + "laterality": laterality, + "protocol": "FLIO", + } + return info_dict + + +def process_ecg_zip(zip_file_path): + try: + with tempfile.TemporaryDirectory() as temp_dir: + with zipfile.ZipFile(zip_file_path, "r") as zip_ref: + zip_ref.extractall(temp_dir) + extracted_files = list_files_recursive(temp_dir) + + ecg_file = [f for f in extracted_files][0] + xdom = minidom.parse(ecg_file) + content = xdom.documentElement.toxml() # a very long string! + my_dict = xmltodict.parse(content) + restingecg = my_dict["restingecgdata"] + + # 4 key items + key_items = dict() + key_items["domain"] = "xml" + key_items["laterality"] = "NA" + key_items["protocol"] = "ECG" + key_items["docname"] = restingecg["documentinfo"]["documentname"] + key_items["pos"] = my_dict["restingecgdata"]["userdefines"]["userdefine"][ + 0 + ]["value"] + key_items["patientid"] = my_dict["restingecgdata"]["patient"][ + "generalpatientdata" + ]["name"]["firstname"] + return key_items + + except Exception as e: + print(f"An error occurred: {str(e)}") + finally: + shutil.rmtree(temp_dir, ignore_errors=True) + return None diff --git a/pyfairdatatools/generate.py b/pyfairdatatools/generate.py index 03e55df..7e65e58 100644 --- a/pyfairdatatools/generate.py +++ b/pyfairdatatools/generate.py @@ -1,10 +1,12 @@ import json from os import makedirs, path from string import Template +from typing import Any, Dict, List from xml.dom.minidom import parseString - +import re import dicttoxml - +import yaml +import requests from . import utils, validate @@ -36,9 +38,9 @@ def generate_dataset_description(data, file_path, file_type): if not path.exists(path.dirname(file_path)): makedirs(path.dirname(file_path)) - RelatedIdentifier = data["RelatedIdentifier"] + relatedIdentifier = data["relatedIdentifier"] - for identifier in RelatedIdentifier: + for identifier in relatedIdentifier: relation_type = identifier["relationType"] if relation_type not in ["HasMetadata", "IsMetadataFor"]: @@ -51,24 +53,6 @@ def generate_dataset_description(data, file_path, file_type): if "schemeType" in identifier: del identifier["schemeType"] - RelatedItem = data["RelatedItem"] - - for item in RelatedItem: - relation_type = item["relationType"] - - relatedItemIdentifier = item["relatedItemIdentifier"] - - for identifier in relatedItemIdentifier: - if relation_type not in ["HasMetadata", "IsMetadataFor"]: - if "relatedMetadataScheme" in identifier: - del identifier["relatedMetadataScheme"] - - if "schemeURI" in identifier: - del identifier["schemeURI"] - - if "schemeType" in identifier: - del identifier["schemeType"] - if file_type == "json": try: with open(file_path, "w", encoding="utf8") as f: @@ -133,42 +117,33 @@ def generate_study_description(data, file_path, file_type): if not path.exists(path.dirname(file_path)): makedirs(path.dirname(file_path)) - StudyType = data["DesignModule"]["StudyType"] - - if StudyType == "Interventional": - if "TargetDuration" in data["DesignModule"]: - del data["DesignModule"]["TargetDuration"] - - if "NumberGroupsCohorts" in data["DesignModule"]: - del data["DesignModule"]["NumberGroupsCohorts"] + studyType = data["designModule"]["studyType"] - if "BioSpec" in data["DesignModule"]: - del data["DesignModule"]["BioSpec"] + if studyType == "Interventional": + if "targetDuration" in data["designModule"]: + del data["designModule"]["targetDuration"] - if "StudyPopulation" in data["EligibilityModule"]: - del data["EligibilityModule"]["StudyPopulation"] + if "numberGroupsCohorts" in data["designModule"]: + del data["designModule"]["numberGroupsCohorts"] - if "SamplingMethod" in data["EligibilityModule"]: - del data["EligibilityModule"]["SamplingMethod"] + if "bioSpec" in data["designModule"]: + del data["designModule"]["bioSpec"] - if StudyType == "Observational": - if "PhaseList" in data["DesignModule"]: - del data["DesignModule"]["PhaseList"] + if "studyPopulation" in data["eligibilityModule"]: + del data["eligibilityModule"]["studyPopulation"] - if "NumberArms" in data["DesignModule"]: - del data["DesignModule"]["NumberArms"] + if "samplingMethod" in data["eligibilityModule"]: + del data["eligibilityModule"]["SamplingMethod"] - ArmGroupList = data["ArmsInterventionsModule"]["ArmGroupList"] + elif studyType == "Observational": + if "phaseList" in data["designModule"]: + del data["designModule"]["phaseList"] - for ArmGroup in ArmGroupList: - if "ArmGroupType" in ArmGroup: - del ArmGroup["ArmGroupType"] + if "numberArms" in data["designModule"]: + del data["designModule"]["numberArms"] - if "ArmGroupInterventionList" in ArmGroup: - del ArmGroup["ArmGroupInterventionList"] - - if "HealthyVolunteers" in data["EligibilityModule"]: - del data["EligibilityModule"]["HealthyVolunteers"] + if "isPatientRegistry" in data["designModule"]: + del data["designModule"]["isPatientRegistry"] if file_type == "json": try: @@ -206,6 +181,358 @@ def generate_study_description(data, file_path, file_type): raise error +def generate_study_description_from_clinical_trials(ct_identifier): + if not (isinstance(ct_identifier, str) and re.match(r"^NCT\d{8}$", ct_identifier.strip())): + print("Invalid identifier, exiting function.") + return + + url = f"https://classic.clinicaltrials.gov/api/v2/studies/{ct_identifier}" + response = requests.get(url, timeout=10) + + if response.status_code == 404: + return { + "error": "No clinical study was found with the provided identifier", + "status_code": 404, + "message": f"No study found for identifier '{ct_identifier}'.", + }, 404 + + cds_data = response.json().get("protocolSection", {}) + status_map = { + "WITHDRAWN": "Withdrawn", + "RECRUITING": "Recruiting", + "ACTIVE_NOT_RECRUITING": "Active, not recruiting", + "NOT_YET_RECRUITING": "Not yet recruiting", + "SUSPENDED": "Suspended", + "ENROLLING_BY_INVITATION": "Enrolling by invitation", + "COMPLETED": "Completed", + "TERMINATED": "Terminated", + } + raw_status = cds_data.get("statusModule", {}).get("overallStatus", "") + identification = cds_data.get("identificationModule", {}) + conditions = cds_data.get("conditionsModule", {}).get("conditions", []) + design = cds_data.get("designModule", {}) + arms_int = cds_data.get("armsInterventionsModule", {}) + eligibility = cds_data.get("eligibilityModule", {}) + contacts = cds_data.get("contactsLocationsModule", {}) + collaborators = cds_data.get("sponsorCollaboratorsModule", {}) + oversight = cds_data.get("oversightModule", {}) + + def bool_to_yes_no(value): + return "Yes" if value is True else "No" if value is False else "" + #Assign criteria for the eligibility + full_criteria = eligibility.get("eligibilityCriteria", "").strip() + inclusion = [] + exclusion = [] + + if "Inclusion Criteria:" in full_criteria: + inclusion_text = full_criteria.split("Inclusion Criteria:")[-1].split("Exclusion Criteria:")[0].strip() + inclusion = [line.strip() for line in inclusion_text.splitlines() if line.strip()] + + if "Exclusion Criteria:" in full_criteria: + exclusion_text = full_criteria.split("Exclusion Criteria:")[-1].strip() + exclusion = [line.strip() for line in exclusion_text.splitlines() if line.strip()] + + data = { + "schema": "", + "identificationModule": { + "officialTitle":identification.get("officialTitle", ""), + "acronym": "", + "orgStudyIdInfo": { + "orgStudyId":identification.get("orgStudyIdInfo", {}).get("id", ""), + "orgStudyIdType":identification.get("orgStudyIdType", {}).get("info", "Other Identifier"), + "orgStudyIdDomain": identification.get("orgStudyIdDomain", {}).get("link", "clinicaltrials.gov") + }, + "secondaryIdInfoList": [{ + "secondaryId": s.get("id", ""), + "secondaryIdType": s.get("type", ""), + "secondaryIdLink": s.get("link", ""), + "secondaryIdDomain": s.get("domain", "nih.gov"), + } for s in identification.get("secondaryIdInfos", [])], + }, + "statusModule": { + "overallStatus": status_map.get(raw_status, raw_status.replace("_", " ").title()), + "startDateStruct": { + "startDate": cds_data.get("statusModule", {}).get("startDateStruct", {}).get("date", ""), + "startDateType": cds_data.get("statusModule", {}).get("startDateStruct", {}).get("type", "").capitalize() + }, + "completionDateStruct": { + "completionDate" : cds_data.get("statusModule", {}).get("completionDateStruct", {}).get("date", ""), + "completionDateType" : cds_data.get("statusModule", {}).get("completionDateStruct", {}).get("type", "").capitalize(), + }, + }, + "sponsorCollaboratorsModule": { + "leadSponsor": { + "leadSponsorName": collaborators.get("leadSponsor", {}).get("name", ""), + }, + "responsibleParty": { + "responsiblePartyType": collaborators.get("responsibleParty", {}).get("type", "") + .replace("_", " ").title(), + }, + "collaboratorList": [ + { + "collaboratorName": c.get("name", ""), + } + for c in collaborators.get("collaborators", [{}]) + ], + }, + "oversightModule": { + "oversightHasDMC": bool_to_yes_no(oversight.get("oversightHasDmc")), + "isFDARegulatedDrug": bool_to_yes_no(oversight.get("isFdaRegulatedDrug")), + "isFDARegulatedDevice": bool_to_yes_no(oversight.get("isFdaRegulatedDevice")), + "humanSubjectReviewStatus": oversight.get("humanSubjectReviewStatus", "Request not yet submitted") + }, + "descriptionModule": { + "briefSummary": cds_data["descriptionModule"]["briefSummary"], + + }, + "conditionsModule": { + "conditionList": [ + { + "conditionName": cnd, + "conditionIdentifier": { + "conditionClassificationCode":"", + "conditionScheme": "", + "schemeURI": "", + "conditionURI": "", + }, + } for cnd in conditions], + }, + "designModule": { + "studyType": design.get("studyType", "").capitalize(), + "phaseList": [re.sub(r'(\d+)', r' \1', p).title() for p in design.get("phases", [])], + "numberArms": design.get("numberArms", "0"), + "enrollmentInfo": { + "enrollmentCount": str(design.get("enrollmentInfo", {}).get("count", "")), + "enrollmentType": design.get("enrollmentInfo", {}).get("type", "").capitalize(), + }, + "isPatientRegistry": bool_to_yes_no(design.get("patientRegistry")), + "bioSpec": { + "bioSpecRetention": design.get("bioSpecRetention", "None Retained"), + "bioSpecDescription": design.get("bioSpecDescription", "None Retained"), + }, + "designInfo": { + "designAllocation": design.get("designInfo", {}).get("allocation", "").replace("_", "-", 1) + .replace("_", " ").replace("-", " ").title(), + "designInterventionModel": design.get("designInfo", {}).get("interventionModel", "") + .replace("_", "-", 1).replace("_", " ").replace("-", " ").title(), + "designPrimaryPurpose": design.get("designInfo", {}).get("primaryPurpose", "") + .replace("_", "-", 1).replace("_", " ").replace("-", " ").title(), + "designMaskingInfo": design.get("designInfo", {}).get("maskingInfo", {}).get("masking", "") + .replace("_", "-", 1).replace("_", " ").replace("-", " ").title(), + "designObservationalModelList": [design.get("designInfo", {}).get("observationalModel", "").replace("_", + "-").capitalize()], + "designTimePerspectiveList": [ + design.get("designInfo", {}).get("timePerspective", "").replace("_", "-").capitalize()] + }, + }, + "armsInterventionsModule": { + "armGroupList": [ + {"armGroupLabel": a.get("label", ""), + "armGroupType": a.get("type", "").replace("_", "-", 1).replace("_", " ").replace("-", " ").title(), + "armGroupDescription": a.get("description", ""), + "armGroupInterventionList": a.get("interventionNames", [])} + for a in arms_int.get("armGroups", {})], + "interventionList": [ + { + "interventionType": i.get("type", "").replace("_", "-", 1).replace("_", " ").replace("-", " ").title(), + "interventionName": i.get("name", ""), + "interventionDescription": i.get("description", ""), + "interventionOtherNameList": i.get("armGroupLabels", "") + } for i in arms_int.get("interventions", [{}]) + ],}, + "eligibilityModule": { + "sex": eligibility.get("sex", "").capitalize(), + "genderBased": eligibility.get("genderBased", "No"), + "minimumAge": eligibility.get("minimumAge", ""), + "maximumAge": eligibility.get("maximumAge", ""), + "healthyVolunteers": bool_to_yes_no(eligibility.get("healthyVolunteers")), + "eligibilityCriteria": { + "eligibilityCriteriaInclusion": inclusion, + "eligibilityCriteriaExclusion": exclusion, + }, + }, + "contactsLocationsModule": { + "centralContactList": [ + { + "centralContactFirstName": c.get("name", ""), + "centralContactLastName": c.get("name", ""), + "centralContactAffiliation": c.get("role", ""), + "centralContactEMail": c.get("email", ""), + } + for c in contacts.get("centralContacts", [])], + "overallOfficialList": [ + { + "overallOfficialFirstName": c.get("name", "").split()[0] if c.get("name") else "", + "overallOfficialLastName": " ".join(c.get("name", "").split()[1:]) if c.get("name") else "", + "overallOfficialAffiliation": { + "overallOfficialAffiliationName": c.get("name", ""), + "overallOfficialAffiliationIdentifier": c.get("identifier", "") + }, + "overallOfficialRole": c.get("role", ""), + + } + for c in contacts.get("overallOfficials", [{}])], + "locationList": [ + { + "locationFacility": c.get("facility", ""), + "locationStatus": c.get("status", "Not yet recruiting"), + "locationCity": c.get("city", ""), + "locationCountry": c.get("county", ""), + + "locationState": c.get("state", ""), + "locationZip": c.get("zip", ""), + "locationContactList": c.get("contactList", ""), + "locationIdentifier": c.get("identifier", ""), + } + for c in contacts.get("locations", [])], + }, + } + # Handling optional leadsponsor fields + lead = collaborators.get("leadSponsor", {}) + identifier = lead.get("identifier") + + # convert an identification type + info_type_list = data["identificationModule"]["secondaryIdInfoList"] + if not info_type_list: + data["identificationModule"].pop("secondaryIdInfoList", None) + else: + for item in info_type_list: + if item.get("secondaryIdType") == "NIH": + item["secondaryIdType"] = "U.S. National Institutes of Health (NIH) Grant/Contract Award Number" + + # Add optional sponsor identifier + if identifier: + data["leadSponsorIdentifier"] = { + "leadSponsorIdentifierValue": identifier.get("value", ""), + "leadSponsorIdentifierScheme": identifier.get("scheme", ""), + "schemeURI": identifier.get("scheme", ""), + } + + # Fix optional responsible party type for the sponsors + rp = collaborators.get("responsibleParty", {}) + rpd = data["sponsorCollaboratorsModule"]["responsibleParty"] + # Split full name + name = rp.get("investigatorFullName", "").strip().split() + if name: + rpd["responsiblePartyInvestigatorFirstName"] = name[0] + rpd["responsiblePartyInvestigatorLastName"] = " ".join(name[1:]) + # Title + if rp.get("investigatorTitle"): + rpd["responsiblePartyInvestigatorTitle"] = rp["investigatorTitle"] + + # Affiliation object handling + aff = rp.get("investigatorAffiliation") + if aff: + rpd["responsiblePartyInvestigatorAffiliation"] = { + "responsiblePartyInvestigatorAffiliationName": aff, + **({"responsiblePartyInvestigatorAffiliationIdentifier": rp["investigatorAffiliationIdentifier"]} + if "investigatorAffiliationIdentifier" in rp else {}) + } + + # Identifier object + x = rp.get("investigatorIdentifier") + if x: + rpd["responsiblePartyInvestigatorIdentifier"] = [{ + "responsiblePartyInvestigatorIdentifierValue": x, + "responsiblePartyInvestigatorIdentifierScheme": x, + "schemeURI": x, + }] + + status_module = data.setdefault("statusModule", {}) + completion_date_struct = status_module.setdefault("completionDateStruct", {}) + + if completion_date_struct.get("completionDateType") == "Estimated": + completion_date_struct["completionDateType"] = "Anticipated" + + # design enrollment info + enrollment_info = data.setdefault("designModule", {}).setdefault("enrollmentInfo", {}) + if enrollment_info.get("enrollmentType") == "Estimated": + enrollment_info["enrollmentType"] = "Anticipated" + + if data.get("statusModule", {}).get("completionDateStruct", {}).get("completionDateType") == "Estimated": + data["statusModule"]["completionDateStruct"]["completionDateType"] = "Anticipated" + + if "whyStopped" in cds_data.get("statusModule", {}): + data.setdefault("statusModule", {})["whyStopped"] = cds_data["statusModule"]["whyStopped"] + + if "keywordList" in cds_data.get("conditionsModule", {}): + data.setdefault("conditionsModule", {})["keywords"] = cds_data["conditionsModule"]["keywordList"] + + for d in ["detailedDescription"]: + if d in cds_data.get("descriptionModule", {}): + data.setdefault("descriptionModule", {})[d] = cds_data["descriptionModule"][d] + + if "orgStudyIdLink" in identification.get("orgStudyIdInfo", {}): + data["identificationModule"]["orgStudyIdInfo"]["orgStudyIdLink"] = identification["orgStudyIdInfo"][ + "orgStudyIdLink"] + + if "targetDuration" in design: + data["designModule"]["targetDuration"] = design["targetDuration"] + #Design assignment + study_type = data["designModule"].get("studyType", "") + + if study_type == "Interventional": + design_info = data.get("designModule", {}).get("designInfo", {}) + for key in ["designTimePerspectiveList", "designObservationalModelList"]: + design_info.pop(key, None) + + bio_spec = data.get("designModule", {}).get("bioSpec", {}) + for key in ["bioSpecRetention", "bioSpecDescription"]: + bio_spec.pop(key, None) + + if study_type == "Observational": + design_info = data.get("designModule", {}).get("designInfo", {}) + for key in ["designAllocation", "designInterventionModel", "designPrimaryPurpose", "designMaskingInfo"]: + design_info.pop(key, None) + + # add optional collab element + collab_info = collaborators.get("collaboratorList", {}) + identifier = collab_info.get("collaboratorNameIdentifier") + + if ( + isinstance(identifier, dict) + and "collaboratorNameIdentifierValue" in identifier + and "collaboratorNameIdentifierScheme" in identifier + ): + data.setdefault("collaboratorModule", {}).setdefault("collaboratorList", {})[ + "collaboratorNameIdentifier"] = identifier + + # Eligibility + for k in ["genderDescription", "studyPopulation", "samplingMethod"]: + if k in eligibility: + v = eligibility[k] + if k == "samplingMethod": + v = {"NON_PROBABILITY_SAMPLE": "Non-Probability Sample", + "PROBABILITY_SAMPLE": "Probability Sample"}.get(v, v) + data["eligibilityModule"][k] = v + + # convert an overall officials type + oo_list = data["contactsLocationsModule"]["overallOfficialList"] + if not oo_list: + data["contactsLocationsModule"].pop("overallOfficialList", None) + else: + role_map = { + "PRINCIPAL_INVESTIGATOR": "Study Principal Investigator", + "CHAIR": "Study Chair", + "DIRECTOR": "Study Director" + } + + for o in oo_list: + raw_role = o.get("overallOfficialRole", "").upper() + o["overallOfficialRole"] = role_map.get(raw_role, "Study Principal Investigator") + + cc_list = data["contactsLocationsModule"]["centralContactList"] + if not cc_list: + data["contactsLocationsModule"].pop("centralContactList", None) + + + file_name = f"clinical_study_description_{ct_identifier}.json" + with open(file_name, "w", encoding="utf-8") as f: + json.dump(data, f, indent=4) + print(f"Saved study description to: {file_name}") + return data + + def generate_readme(data, file_path, file_type): """Generate a readme file. @@ -381,3 +708,77 @@ def generate_license_file( else: print("Could not get text for license.") raise NotImplementedError("License text not available") + + +def generate_datatype_file(data, file_path, file_type): + """Generate a datatype file. + + Args: + data (list): The list of datatypes to generate + file_path (str): The path to the folder to save the datatype in + file_type (str): The type of file to save the datatype as + Returns: + A datatype dictionary yaml file + """ + ALLOWED_FILE_TYPES = ["yaml"] + + try: + if file_type not in ALLOWED_FILE_TYPES: + print("File type is invalid.") + raise ValueError("Invalid file type") + + if not utils.validate_file_path(file_path, writable=True): + print("File path is invalid.") + raise ValueError("Invalid file path") + + if not validate.validate_datatype_dictionary(data): + print("Datatype is invalid.") + raise ValueError("Invalid input data") + + if not path.exists(path.dirname(file_path)): + makedirs(path.dirname(file_path)) + + # Create the datatype file before generating the datatype description file + datatype_data: Dict[str, List[Dict[str, Any]]] = {"datatype_dictionary": []} + + with open( + path.join(path.dirname(__file__), "assets", "datatype_dictionary.yaml"), + encoding="utf-8", + ) as f: + schema = yaml.safe_load(f) + + for entry in data: + for item in schema["datatype_dictionary"]: + if entry == item["code_name"] or entry in item["aliases"]: + print(item) + new_item = {} + if "code_name" in item: + new_item["code_name"] = item["code_name"] + if "datatype_description" in item: + new_item["datatype_description"] = item["datatype_description"] + if "aliases" in item: + new_item["aliases"] = item["aliases"] + if "related_terms" in item: + new_item["related_terms"] = item["related_terms"] + if "related_standards" in item: + new_item["related_standards"] = item["related_standards"] + datatype_data["datatype_dictionary"].append(new_item) + + if file_type == "yaml": + try: + with open(file_path, "w", encoding="utf8") as f: + yaml.dump(datatype_data, f, indent=4, sort_keys=False) + except Exception as error: + print(error) + raise error + + elif file_type not in ["yaml"]: + print("File type is invalid.") + raise ValueError("Invalid file type") + + except ValueError as error: + print(error) + raise ValueError("Invalid input") from error + except Exception as error: + print(error) + raise error diff --git a/pyfairdatatools/identifier.py b/pyfairdatatools/identifier.py new file mode 100644 index 0000000..ada600d --- /dev/null +++ b/pyfairdatatools/identifier.py @@ -0,0 +1,36 @@ +from classifying_rules import ( + process_dicom_zip, + process_ecg_zip, + process_env_zip, + process_flio_zip, +) + + +def data_identifier(zip_file_path): + if not zip_file_path.endswith(".zip"): + return "Not a zip file" + + elif "ENV" in zip_file_path: + return process_env_zip(zip_file_path) + + elif "xml" in zip_file_path: + return process_ecg_zip(zip_file_path) + + elif "FLIO" in zip_file_path: + return process_flio_zip(zip_file_path) + + elif any( + word in zip_file_path + for word in [ + "Optomed", + "Eidon", + "Maestro", + "Triton", + "Cirrus", + "Spectralis", + ] + ): + return process_dicom_zip(zip_file_path) + + else: + return "Unknown file type" diff --git a/pyfairdatatools/schemas/dataset_description.schema.json b/pyfairdatatools/schemas/dataset_description.schema.json index 79c6f1f..33dd628 100644 --- a/pyfairdatatools/schemas/dataset_description.schema.json +++ b/pyfairdatatools/schemas/dataset_description.schema.json @@ -1,237 +1,375 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schema.aireadi.org/files/dataset_description.json", + "$id": "https://schema.aireadi.org/v0.1.0/dataset_description.json", + "$schema": "http://json-schema.org/draft-07/schema", "title": "Dataset Description", - "description": "This is the schema for the dataset_description.json metadata file from the Biomedical and Clinical Dataset Structure (BCDS)", + "description": "This is the schema for the dataset_description.json metadata file from the Clinical Dataset Structure (CDS). The keys, descriptions, requirements, examples, etc. are from the DataCite Metadata Schema v4.5 unless specified otherwise in $comment. Note that the 'GeoLocation' and 'RelatedItem' properties from Datacite are not included as they were not deemed relevant for the use case in the CDS. Some keys are from the the ECRIN Metadata Schema for data object v6.0 and we have introduced some modifications as necessary for tailoring the schema to clinical research datasets. All keys are camelCase.", "type": "object", "additionalProperties": false, "properties": { - "Identifier": { + "schema": { + "description": "Link to the schema to be included so that users of the resulting JSON file can find the related schema easily", + "type": "string", + "const": "https://schema.aireadi.org/v0.1.0/dataset_description.json" + }, + "identifier": { "type": "object", "additionalProperties": false, "properties": { "identifierValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is based on the DataCite Metadata Schema v4.5 for 'identifier' but modified to suit datasets. In DataCite, only a DOI is allowed, but here, any identifier is allowed", "type": "string", "minLength": 1, - "description": "Unique string that identifies the dataset." + "description": "Unique string that identifies the dataset.", + "examples": [ + "10.21384/foo" + ] }, "identifierType": { - "$ref": "#/$defs/identifierType", - "description": "The type of identifier used to identify the dataset." + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets. In Datacite this must be 'DOI' but here, any type of identifier is allowed.", + "$ref": "#/definitions/identifierType", + "description": "The type of identifier used to identify the dataset. Must be from the controlled list of identifierType." } }, - "required": ["identifierValue", "identifierType"] + "required": [ + "identifierValue", + "identifierType" + ] }, - "Title": { + "title": { "type": "array", "items": { - "$ref": "#/$defs/titleItem" + "$ref": "#/definitions/titleItem" }, "description": "The main title of the dataset is mandatory. Others are optional", "minItems": 1, "uniqueItems": true }, - "Version": { + "version": { + "$comment": "Description is from DataCite Metadata Schema v4.5 but modified to suit dataset. It is not mandatory in the DataCite Schema but it is mandatory here.", "type": "string", - "description": "The version number of the dataset. Suggested practice: major_version.minor_version. Register a new identifier for a major version change. ", - "minLength": 1 + "description": "The version number of the dataset. Suggested practice: major_version.minor_version. Register a new identifier for a major version change. May be used in conjunction with properties 'alternateIdentifier' and 'relatedIdentifier' to indicate various information updates. May be used in conjunction with property 'description' to indicate the nature and file/record range of version.", + "minLength": 1, + "examples": [ + "2.1" + ] }, - "AlternateIdentifier": { + "alternateIdentifier": { "type": "array", - "description": "An identifier other than the primary Identifier applied to the resource being registered. This may be any alphanumeric string which is unique within its domain of issue. May be used for local identifiers. The AlternateIdentifier should be an additional identifier for the same instance of the resource (i.e., same location, same file).", "items": { "type": "object", "additionalProperties": false, "properties": { "alternateIdentifierValue": { + "$comment": "This key has been added to fit the JSON structure. Description is based on the DataCite Metadata Schema v4.5 for 'identifier' but modified to suit datasets.", "type": "string", "minLength": 1, - "description": "An identifier other than the primary Identifier applied to the dataset. This may be any alphanumeric string which is unique within its domain of issue. May be used for local identifiers." + "description": "An identifier other than the primary 'identifier' applicable for the dataset. This may be any alphanumeric string which is unique within its domain of issue. May be used for local identifiers.", + "examples": [ + "E-GEOD-34814" + ] }, "alternateIdentifierType": { - "$ref": "#/$defs/identifierType", - "description": "The type of identifier used to identify the dataset." + "$comment": "In the DataCite Metadata Schema v4.5 free text is allowed here but here it must be from the controlled list of identifierType", + "$ref": "#/definitions/identifierType", + "description": "The type of the alternateIdentifier. Must be from the controlled list of identifierType." } }, - "required": ["alternateIdentifierValue", "alternateIdentifierType"] + "required": [ + "alternateIdentifierValue", + "alternateIdentifierType" + ] }, "minItems": 1, "uniqueItems": true }, - "Creator": { + "creator": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", "type": "array", + "description": "The main researchers involved in producing the data, in priority order. To supply multiple creators, repeat this property.", "items": { "type": "object", "additionalProperties": false, - "description": "A researcher involved in producing the data.", "properties": { "creatorName": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified for clarity.", "type": "string", "minLength": 1, - "description": "The full name of the creator. Should be in the format: `family name, given name`. If the creator is an organization, the name should be in the format: `Organization name`." + "description": "The full name of the creator (personal name or organization name). Note that the personal name format should be: family, given. Names in non-roman scripts may be transliterated according to the ALA-LC tables https://www.loc.gov/catdir/cpso/roman.html.", + "examples": [ + "Garcia, Sofia" + ] }, "nameType": { - "$ref": "#/$defs/typeOfNameOfPersonOrOrganization", - "description": "The type of name." + "$comment": "Not mandatory in the DataCite Metadata Schema v4.5 but mandatory here", + "$ref": "#/definitions/nameType", + "description": "The type of name. Must be from the controlled list of nameType." }, "nameIdentifier": { "type": "array", - "description": "", + "description": "Uniquely identifies an individual or legal entity, according to various schemes.", "items": { "type": "object", "additionalProperties": false, "properties": { "nameIdentifierValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. It is not clear from the DataCite documentation if the scheme URI should be included in the value. Here, the scheme URI must be included in the value.", "type": "string", "minLength": 1, - "description": "Uniquely identifies an individual or legal entity, according to various schemes." + "description": "Uniquely identifies an individual or legal entity, according to various schemes.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427", + "https://isni.org/isni/0000000492299539", + "https://ror.org/04aj4c18" + ] }, "nameIdentifierScheme": { "type": "string", "minLength": 1, - "description": "The name of the name identifier scheme. Example: ORCID, ISNI, ROR, GRID." + "description": "The name of the name identifier scheme.", + "examples": [ + "ORCID", + "ISNI", + "ROR" + ] }, "schemeURI": { "type": "string", "minLength": 1, - "description": "The URI of the name identifier scheme. Example: https://ror.org, https://isni.org, https://orcid.org, https://grid.ac" + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://orcid.org", + "https://isni.org", + "https://ror.org" + ] } }, - "required": ["nameIdentifierValue", "nameIdentifierScheme"] + "required": [ + "nameIdentifierValue", + "nameIdentifierScheme" + ] }, "uniqueItems": true }, "affiliation": { "type": "array", - "description": "The organizational or institutional affiliation of the creator. Only needed if the creator is a person", + "description": "The organizational or institutional affiliation of the creator.", "items": { "type": "object", "additionalProperties": false, "properties": { - "affiliationValue": { + "affiliationName": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is based on the DataCite Metadata schema v4.5 for 'affiliation' but has been modified for clarity.", "type": "string", "minLength": 1, - "description": "The name of the organizational or institutional affiliation of the creator. required if identifier is not provided." + "description": "Name of the organizational or institutional affiliation of the creator. In the case of an organizational creator, e.g., a research group, this will often be the name of the institution to which that organization belongs.", + "examples": [ + "German National Library of Science and Technology", + "DataCite" + ] }, "affiliationIdentifier": { - "type": "string", - "minLength": 1, - "description": "Uniquely identifies the organizational affiliation of the creator. required if value is not provided." - }, - "affiliationIdentifierScheme": { - "type": "string", - "minLength": 1, - "description": "The name of the name identifier scheme. Example: ORCID, ISNI, ROR, GRID." - }, - "schemeURI": { - "type": "string", - "minLength": 1, - "description": "The URI of the name identifier scheme. Example: https://ror.org, https://isni.org, https://orcid.org, https://grid.ac" + "$comment": "Created an object for the identifier here to better handle requirements", + "type": "object", + "additionalProperties": false, + "properties": { + "affiliationIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies the organizational affiliation of the creator.", + "examples": [ + "https://ror.org/04aj4c181", + "https://isni.org/isni/0000000492299539" + ] + }, + "affiliationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the name identifier scheme. If affiliationIdentifier is used, affiliationIdentifierScheme is mandatory.", + "examples": [ + "ISNI", + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://isni.org", + "https://ror.org" + ] + } + }, + "required": [ + "affiliationIdentifierValue", + "affiliationIdentifierScheme" + ] } }, - "required": [] + "required": [ + "affiliationName" + ] }, + "minItems": 1, "uniqueItems": true } }, - "required": ["creatorName", "nameType"] + "required": [ + "creatorName", + "nameType" + ] }, - "description": "The main researchers involved in producing the data, in priority order. To supply multiple creators, repeat this property.", "minItems": 1, "uniqueItems": true }, - "Contributor": { + "contributor": { "type": "array", + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", + "description": "The institution or person responsible for collecting, managing, distributing, or otherwise contributing to the development of the dataset. To supply multiple contributors, repeat this property.", "items": { "type": "object", "additionalProperties": false, - "description": "", "properties": { "contributorType": { - "$ref": "#/$defs/contributorType", - "description": "The type of contributor of the resource" + "$ref": "#/definitions/contributorType", + "description": "The type of contributor of the resource. Must be from the controlled list of contributorType." }, "contributorName": { "type": "string", "minLength": 1, - "description": "The full name of the contributor. Should be in the format: `family name, given name`. If the creator is an organization, the name should be in the format: `Organization name`." + "description": "The full name of the contributor. The personal name format should be: family, given. Non-roman names should be transliterated according to the ALA-LC schemas https://www.loc.gov/catdir/cpso/roman.html." }, "nameType": { - "$ref": "#/$defs/typeOfNameOfPersonOrOrganization", - "description": "The type of name." + "$comment": "Not mandatory in the DataCite schema but mandatory here", + "$ref": "#/definitions/nameType", + "description": "The type of name. Must be from the list of controlled values nameType." }, "nameIdentifier": { "type": "array", - "description": "", + "description": "Uniquely identifies an individual or legal entity, according to various schemes.", "items": { "type": "object", "additionalProperties": false, "properties": { "nameIdentifierValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. It is not clear from the DataCite documentation if the scheme URI should be included in the value. Here, the scheme URI must be included in the value.", "type": "string", "minLength": 1, - "description": "Uniquely identifies an individual or legal entity, according to various schemes." + "description": "Uniquely identifies an individual or legal entity, according to various schemes.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427", + "https://isni.org/isni/0000000492299539", + "https://ror.org/04aj4c18" + ] }, "nameIdentifierScheme": { "type": "string", "minLength": 1, - "description": "The name of the name identifier scheme. Example: ORCID, ISNI, ROR, GRID." + "description": "The name of the name identifier scheme.", + "examples": [ + "ORCID", + "ISNI", + "ROR" + ] }, "schemeURI": { "type": "string", "minLength": 1, - "description": "The URI of the name identifier scheme. Example: https://ror.org, https://isni.org, https://orcid.org, https://grid.ac" + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://orcid.org", + "https://isni.org", + "https://ror.org" + ] } }, - "required": ["nameIdentifierValue", "nameIdentifierScheme"] + "required": [ + "nameIdentifierValue", + "nameIdentifierScheme" + ] }, "minItems": 1, "uniqueItems": true }, "affiliation": { "type": "array", - "description": "The organizational or institutional affiliation of the creator. Only needed if the creator is a person", + "description": "The organizational or institutional affiliation of the creator.", "items": { "type": "object", "additionalProperties": false, "properties": { - "affiliationValue": { + "affiliationName": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is based on the DataCite Metadata schema v4.5 for 'affiliation' but has been modified for clarity.", "type": "string", "minLength": 1, - "description": "The name of the organizational or institutional affiliation of the creator. required if identifier is not provided." + "description": "Name of the organizational or institutional affiliation of the creator. In the case of an organizational creator, e.g., a research group, this will often be the name of the institution to which that organization belongs.", + "examples": [ + "German National Library of Science and Technology", + "DataCite" + ] }, "affiliationIdentifier": { - "type": "string", - "minLength": 1, - "description": "Uniquely identifies the organizational affiliation of the creator. required if value is not provided." - }, - "affiliationIdentifierScheme": { - "type": "string", - "minLength": 1, - "description": "The name of the name identifier scheme. Example: ORCID, ISNI, ROR, GRID." - }, - "schemeURI": { - "type": "string", - "minLength": 1, - "description": "The URI of the name identifier scheme. Example: https://ror.org, https://isni.org, https://orcid.org, https://grid.ac" + "$comment": "Created an object for the identifier here to better handle requirements", + "type": "object", + "additionalProperties": false, + "properties": { + "affiliationIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies the organizational affiliation of the creator.", + "examples": [ + "https://ror.org/04aj4c181", + "https://isni.org/isni/0000000492299539" + ] + }, + "affiliationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the name identifier scheme. If affiliationIdentifier is used, affiliationIdentifierScheme is mandatory.", + "examples": [ + "ISNI", + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://isni.org", + "https://ror.org" + ] + } + }, + "required": [ + "affiliationIdentifierValue", + "affiliationIdentifierScheme" + ] } }, - "required": [] + "required": [ + "affiliationName" + ] }, "minItems": 1, "uniqueItems": true } }, - "required": ["contributorType", "contributorName", "nameType"] + "required": [ + "contributorType", + "contributorName", + "nameType" + ] }, - "description": "The institution or person responsible for collecting, managing, distributing, or otherwise contributing to the development of the dataset. To supply multiple contributors, repeat this property.", "uniqueItems": true }, - "PublicationYear": { - "$ref": "#/$defs/publicationYear", - "description": "The year in which the dataset was published." + "publicationYear": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", + "$ref": "#/definitions/publicationYear", + "description": "The year when the data was or will be made publicly available. In the case of dynamic data where there may be multiple releases in one year, include the 'date', 'dateType', and 'dateInformation' property and sub-properties to provide more information about the publication or release date details." }, - "Date": { + "date": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", "type": "array", "description": "Different dates relevant to the dataset", "items": { @@ -239,19 +377,22 @@ "additionalProperties": false, "properties": { "dateValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure", "type": "string", "minLength": 1, - "description": "YYYY, YYYY-MM-DD, YYYY-MM-DDThh:mm:ssTZD or any other format or level of granularity described in W3CDTF22. Use RKMS-ISO860123 standard for depicting date ranges.", + "description": "YYYY, YYYY-MM-DD, YYYY-MM-DDThh:mm:ssTZD or any other format or level of granularity described in W3CDTF22 https://www.w3.org/TR/NOTE-datetime. Use RKMS-ISO860123 https://www.ukoln.ac.uk/metadata/dcmi/collection-RKMS-ISO8601/ standard for depicting date ranges. Years before 0000 must be prefixed with a - sign, e.g., -0054 to indicate 55 BC.", "examples": [ "2004", "2004-03-02", "2004-03-02T00:00:00Z", - "2004-03-02T00:00:00.000Z" + "2004-03-02T00:00:00.000Z", + "2004-03-02/2005-06-02" ] }, "dateType": { + "$comment": "The options and their descriptions are exactly from DataCite Metadata Schema v4.5 extended with few options from the 'date_type' in the ECRIN Metadata schema v6.0 for data object. ECRIN options have been Pascal Cased to align with DataCite options.", "type": "string", - "description": "The type of date.", + "description": "The type of date. Must be from the controlled list.", "oneOf": [ { "const": "Accepted", @@ -294,10 +435,12 @@ "description": "The date the resource is removed." }, { + "$comment": "From ECRIN", "const": "ControlledAccessInForce", "description": "The date the resource is made available under controlled access of some form. May be a range. To indicate the end of such a period, use Available." }, { + "$comment": "From ECRIN", "const": "Other", "description": "Date type not defined elsewhere." } @@ -306,87 +449,61 @@ "dateInformation": { "type": "string", "minLength": 1, - "description": "Additional information about the date, if needed" + "description": "Specific information about the date, if appropriate. May be used to provide more information about the publication, release, or collection date details, for example. May also be used to clarify dates in ancient history. Examples: 55 BC, 55 BCE." } }, - "required": ["dateValue", "dateType"] + "required": [ + "dateValue", + "dateType" + ] }, "minItems": 1, "uniqueItems": true }, - "ResourceType": { + "resourceType": { "type": "object", "additionalProperties": false, "description": "Description of the type of dataset", "properties": { "resourceTypeValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Example is customized for clinical datasets.", "type": "string", "minLength": 1, - "description": "Free text. The recommended content is a single term of some detail about the domain or content of the dataset so that a pair can be formed with the resourceTypeGeneral subproperty (set to `Dataset`). For example, a resourceType of `Diabetes` yields `Diabetes dataset`" + "description": "Free text. The recommended content is a single term of some detail about the domain or content of the dataset so that a pair can be formed with the resourceTypeGeneral subproperty (set to `Dataset`). For example, a resourceType of `Diabetes` yields `Diabetes Dataset`.", + "examples": [ + "Diabetes" + ] }, "resourceTypeGeneral": { "type": "string", - "description": "The general type of a resource.", + "description": "The general type of a resource. While there are several options possible in the DataCite Schema, it must always be 'dataset' here.", "pattern": "Dataset" } }, - "required": ["resourceTypeValue", "resourceTypeGeneral"] - }, - "DatasetRecordKeys": { - "type": "object", - "additionalProperties": false, - "description": "A set of keys that uniquely identify the dataset within the repository", - "properties": { - "keysType": { - "type": "string", - "description": "Provides an indication of the types of keys used in the dataset, in particular if they are claimed to be anonymous or pseudonymous", - "oneOf": [ - { - "const": "NotKnown", - "description": "No clear information available about the record keys in use." - }, - { - "const": "Anonymised", - "description": "Data controller or manager describes dataset as `anonymised`, in their interpretation of the term." - }, - { - "const": "Pseudonymised", - "description": "Data controller or manager describes dataset as `pseudonymised`, in their interpretation of the term." - }, - { - "const": "Identifiable", - "description": "Data controller or manager describes dataset as `identifiable`, in their interpretation of the term." - } - ] - }, - "keysDetails": { - "type": "string", - "minLength": 1, - "description": "Provides further details of the record key types, perhaps referring to dataset preparation, if available" - } - }, - "required": ["keysType"] + "required": [ + "resourceTypeValue", + "resourceTypeGeneral" + ] }, - "DatasetDeIdentLevel": { + "datasetDeIdentLevel": { + "$comment": "This key is from the ECRIN Metadata Schema for data object v6.0 'E.4 De-identification level'. Description has been modified to suit datasets.", "type": "object", "additionalProperties": false, - "description": "For dataset objects only, indicates the level of de-identification applied to the dataset", + "description": "Indicates the level of de-identification applied to the dataset", "properties": { "deIdentType": { + "$comment": "The 'NotKnown' option from ECRIN has been removed here. The options have been Pascal Cased to align with the overall controlled values.", "type": "string", - "description": "Provide an indication of the level of deidentification of the dataset", + "description": "Provides an indication of the level of deidentification of the dataset. Must be from the controlled list.", "oneOf": [ - { - "const": "NotKnown", - "description": "No clear information available about the de-identification, if any, applied to the data." - }, { "const": "NoDeIdentification", "description": "Confirmed that no de-identification measures have been applied to the data set." }, { + "$comment": "Description modified to suit datasets", "const": "DeIdentificationApplied", - "description": "Some de-identification measures have been applied. Details should be described in comments and / or indicated in the linked boolean fields, or in separate documents." + "description": "Some de-identification measures have been applied. Details should be described indicated in the linked boolean fields and/or in separate documents." }, { "const": "DeIdentificationAppliedPrimaryOutcomesReAssessed", @@ -429,19 +546,17 @@ "deIdentKAnon" ] }, - "DatasetConsent": { + "datasetConsent": { + "$comment": "This key is from the ECRIN Metadata Schema for data object v6.0 'E.5 Associated consent'. Description has been modified to suit datasets.", "type": "object", "additionalProperties": false, - "description": "For dataset objects only, provides an indication of the level of explicit consent for secondary use of the data", + "description": "Provide an indication of the level of explicit consent for secondary use of the data.", "properties": { "consentType": { + "$comment": "The 'NotKnown' option from ECRIN has been removed here. The options have been Pascal Cased to align with the overall controlled values.", "type": "string", - "description": "One of the allowed types, from the dataset_consent_types enumeration, e.g. `No explicit consent`, or `General research use`", + "description": "Must be from the controlled list", "oneOf": [ - { - "const": "NotKnown", - "description": "No clear information available about consent for secondary use, or if any exists." - }, { "const": "NoExplicitConsent", "description": "No specific consent was given for the sharing of data or its re-use beyond the study in which it was originally collected." @@ -503,25 +618,27 @@ "consentNoMethods" ] }, - "Description": { + "description": { "type": "array", - "description": "All additional information that does not fit in any of the other categories. May be used for technical information.", + "description": "All additional information that does not fit in any of the other categories. It is a best practice to supply a description. ", "items": { "type": "object", "additionalProperties": false, "properties": { "descriptionValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure", "type": "string", "minLength": 1, "description": "A description associated with the dataset" }, "descriptionType": { + "$comment": "Some option from DataCite Metadata Schema v4.5 controlled list have been removed since they were not deemed relevant to clinical research datasets.", "type": "string", - "description": "The type of the Description", + "description": "The type of the 'description'. Must be from controlled list.", "oneOf": [ { "const": "Abstract", - "description": "A brief description of the resource and the context in which the resource was created", + "description": "A brief description of the resource and the context in which the resource was created", "examples": [ "https://data.datacite.org/application/vnd.datacite.datacit e+xml/10.1594/PANGAEA.771774" ] @@ -533,20 +650,9 @@ "https://data.datacite.org/application/vnd.datacite.datacit e+xml/10.6078/D1K01X" ] }, - { - "const": "SeriesInformation", - "description": "Information about a repeating series, such as volume, issue, number." - }, - { - "const": "TableOfContents", - "description": "A listing of the Table of Contents.", - "examples": [ - "https://data.datacite.org/application/vnd.datacite.datacit e+xml/10.5678/LCRS/FOR816.CIT.1031" - ] - }, { "const": "TechnicalInfo", - "description": "Detailed information that may be associated with design, implementation, operation, use, and/or maintenance of a process or system." + "description": "Detailed information that may be associated with design, implementation, operation, use, and/or maintenance of a process or system." }, { "const": "Other", @@ -555,16 +661,22 @@ ] } }, - "required": ["descriptionType", "descriptionValue"] + "required": [ + "descriptionType", + "descriptionValue" + ] }, "uniqueItems": true }, - "Language": { + "language": { "type": "string", "minLength": 2, - "description": "The primary language used in the dataset. Allowed values are taken from IETF BCP 47, ISO 639-1 language codes" + "description": "The primary language used in the dataset. Allowed values are taken from IETF BCP 47 https://en.wikipedia.org/wiki/IETF_language_tag, ISO 639-1 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes language codes", + "examples": [ + "en" + ] }, - "RelatedIdentifier": { + "relatedIdentifier": { "type": "array", "description": "Identifiers of related resources. These must be globally unique identifiers.", "items": { @@ -572,17 +684,19 @@ "additionalProperties": false, "properties": { "relatedIdentifierValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure", "type": "string", "minLength": 1, "description": "Identifier of the related resource. Must be globally unique." }, "relatedIdentifierType": { - "$ref": "#/$defs/identifierType", - "description": "The type of the RelatedIdentifier." + "$ref": "#/definitions/identifierType", + "description": "The type of the relatedIdentifier. Must be from the controlled list of identifierType." }, "relationType": { - "$ref": "#/$defs/relationType", - "description": "The type of relationship between the resource being registered and the RelatedIdentifier." + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", + "$ref": "#/definitions/relationType", + "description": "The type of relationship between the dataset (A) and the related resource (B). Must be from the controlled list of relationType." }, "relatedMetadataScheme": { "type": "string", @@ -598,11 +712,15 @@ "type": "string", "minLength": 1, "description": "The type of the relatedMetadataScheme, linked with the schemeURI. Use only with this relation pair: (HasMetadata/ IsMetadataFor)", - "examples": ["XSD", "DDT", "Turtle"] + "examples": [ + "XSD", + "DDT", + "Turtle" + ] }, "resourceTypeGeneral": { - "$ref": "#/$defs/resourceItemType", - "description": "The general type of the related resource." + "$ref": "#/definitions/resourceItemType", + "description": "The general type of the related resource. Must be from the controlled list of resourceItemType." } }, "required": [ @@ -613,73 +731,133 @@ }, "uniqueItems": true }, - "Subject": { + "subject": { "type": "array", - "description": "Subject, keyword, classification code, or key phrase describing the resource", "items": { + "$comment": "Examples have be adapted for clinical research datasets", "type": "object", "additionalProperties": false, "description": "", "properties": { "subjectValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure", "type": "string", "minLength": 1, - "description": "The subject, keyword, classification code, or key phrase that describes the resource" - }, - "subjectScheme": { - "type": "string", - "minLength": 1, - "description": "The name of the subject scheme or classification code or authority if one is used", + "description": "The subject, keyword, classification code, or key phrase that describes the dataset", "examples": [ - "Library of Congress Subject Headings (LCSH)", - "ANZSRC Fields of Research" + "Diabetes mellitus" ] }, - "schemeURI": { - "type": "string", - "minLength": 1, - "description": "The URI of the subject identifier scheme", - "examples": ["https://id.loc.gov/authorities/subjects.html"] - }, - "valueURI": { - "type": "string", - "minLength": 1, - "description": "The URI of the subject term", - "examples": [ - "https://id.loc.gov/authorities/subjects/sh85118622.html" + "subjectIdentifier": { + "$comment": "Created an object for the identifier here to better handle requirements", + "type": "object", + "additionalProperties": false, + "properties": { + "classificationCode": { + "$comment": "Made required here as part of the identifier object", + "type": "string", + "minLength": 1, + "description": "The classification code used for the subject term in the subject scheme", + "examples": [ + "45636-8" + ] + }, + "subjectScheme": { + "$comment": "Made required here as part of the identifier object. Description is based on the DataCite Metadata Schema v4.5 but extended to provide more clarity.", + "type": "string", + "minLength": 1, + "description": "The name of the subject scheme or classification code or authority if one is used (e.g., name of ontology)", + "examples": [ + "Logical Observation Identifier Names and Codes (LOINC)" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the subject identifier scheme", + "examples": [ + "https://loinc.org/" + ] + }, + "valueURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the subject term", + "examples": [ + "https://loinc.org/45636-8" + ] + } + }, + "required": [ + "classificationCode", + "subjectScheme" ] - }, - "classificationCode": { - "type": "string", - "minLength": 1, - "description": "The classification code used for the subject term in the subject scheme" } }, - "required": ["subjectValue"] + "required": [ + "subjectValue" + ] }, "uniqueItems": true }, - "ManagingOrganisation": { + "managingOrganization": { + "$comment": "This key is from the ECRIN Metadata Schema for data objects v6.0 'F.1 Managing Organization'", "type": "object", "additionalProperties": false, - "description": "The organisation managing the object, in particular that determines access to it", "properties": { "name": { + "$comment": "Description has been modified for clarity", "type": "string", "minLength": 1, - "description": "The name of the organisation managing the object" - }, - "rorId": { - "type": "string", - "minLength": 1, - "description": "The id of the organisation, if known, within the ROR (Research Organisation Registry) system. This is a URL linking to the ROR resource." + "description": "The name of the organization managing the dataset, in particular that determines access to it" + }, + "managingOrganizationIdentifier": { + "$comment": "ECRIN only allow for ROR Id but it has been extended here following the example of other organization identifier in DataCite schema to be more flexible and accomodate other identifiers", + "type": "object", + "additionalProperties": false, + "properties": { + "managingOrganizationIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies the managing organization.", + "examples": [ + "https://ror.org/04aj4c181", + "https://isni.org/isni/0000000492299539" + ] + }, + "managingOrganizationScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the organization identifier scheme. If affiliationIdentifier is used, affiliationIdentifierScheme is mandatory.", + "examples": [ + "ISNI", + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the identifier scheme.", + "examples": [ + "https://isni.org", + "https://ror.org" + ] + } + }, + "required": [ + "managingOrganizationIdentifierValue", + "managingOrganizationScheme" + ] } }, - "required": ["name"] + "required": [ + "name" + ] }, - "AccessType": { + "accessType": { + "$comment": "The 'NotKnownYet' option has been removed since it is not relevant here. The options have been Pascal Cased to align with the overall controlled values", "type": "string", - "description": "The type of access to the object", + "description": "The type of access to the dataset. Must be from controlled list", "oneOf": [ { "const": "PublicOnScreenAccess", @@ -724,14 +902,11 @@ { "const": "Other", "description": "None of the listed options." - }, - { - "const": "NotYetKnown", - "description": "Dummy value supplied by default on entity creation." } ] }, - "AccessDetails": { + "accessDetails": { + "$comment": "This key is from the ECRIN Metadata Schema for data objects v6.0 'F.3 Access Details'", "type": "object", "additionalProperties": false, "description": "Further details of the access (especially if non public)", @@ -745,68 +920,163 @@ "type": "string", "minLength": 1, "pattern": "^(https?|ftp)://[^s/$.?#].[^s]*$", - "description": "A url of a web page that provides details of the accesss available, possibly including the practical details required or a form to use to apply for access" + "description": "A url of a web page that provides details of the access available, possibly including the practical details required or a form to use to apply for access" }, "urlLastChecked": { + "$comment": "Format changed to match DataCite date format", "type": "string", "format": "date-time", "description": "If a check has been carried out, the date the url last responded with a 200 (success) message, as a string " } }, - "required": ["description"] + "required": [ + "description" + ] }, - "Rights": { + "rights": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to for more clarity. It is not mandatory in the DataCite schema but is mandatory here.", "type": "array", - "description": "The rights associated with the object", + "description": "The license associated with the dataset. The property may be repeated to record complex rights characteristics.", "items": { "type": "object", "additionalProperties": false, "properties": { - "rightsValue": { + "rightsName": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure", "type": "string", "minLength": 1, "description": "Use the complete title of a license and include version information if applicable", - "examples": ["CMU License", "MIT License Modern Variant"] + "examples": [ + "Creative Commons Attribution 4.0 International" + ] }, "rightsURI": { "type": "string", "minLength": 1, "description": "The URI of the license", - "examples": ["https://creativecommons.org/licenses/by/4.0/"] + "examples": [ + "https://creativecommons.org/licenses/by/4.0/" + ] }, "rightsIdentifier": { - "type": "string", - "minLength": 1, - "description": "The identifier of the rights statement. A list of identifiers for commonly-used licenses may be found here: (https://spdx.org/licenses/)", - "examples": ["CC-BY-4.0", "CC-BY-NC-4.0", "MIT", "MIT-CMU"] - }, - "rightsIdentifierScheme": { - "type": "string", - "minLength": 1, - "description": "The name of the rights identifier scheme or authority if one is used", - "examples": ["SPDX"] + "$comment": "Created an object for the identifier here to better handle requirements", + "type": "object", + "additionalProperties": false, + "properties": { + "rightsIdentifierValue": { + "$comment": "Made required here as part of the object", + "type": "string", + "minLength": 1, + "description": "A short, standardized version of the license name. A list of identifiers for commonly-used licenses may be found here: (https://spdx.org/licenses/)", + "examples": [ + "CC-BY-4.0" + ] + }, + "rightsIdentifierScheme": { + "$comment": "Made required here as part of the object", + "type": "string", + "minLength": 1, + "description": "The name of the scheme", + "examples": [ + "SPDX" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the rightsIdentifierScheme", + "examples": [ + "https://spdx.org/licenses/" + ] + } + }, + "required": [ + "rightsIdentifierValue", + "rightsIdentifierScheme" + ] } }, - "required": ["rightsValue"] + "required": [ + "rightsName" + ] }, "uniqueItems": true }, - "Publisher": { - "$ref": "#/$defs/publisher", - "description": "The name of the entity that holds, archives, publishes prints, distributes, releases, issues, or produces the dataset. This property will be used to formulate the citation, so consider the prominence of the role." + "publisher": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit the JSON structure", + "description": "Information about the entity that holds, archives, publishes prints, distributes, releases, issues, or produces the dataset.", + "type": "object", + "additionalProperties": false, + "properties": { + "publisherName": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is based on the DataCite Metadata Schema v4.5 for 'publisher' but modified to suit dataset.", + "type": "string", + "minLength": 1, + "description": "Name of the entity that holds, archives, publishes prints, distributes, releases, issues, or produces the dataset.", + "examples": [ + "FAIRhub" + ] + }, + "publisherIdentifier": { + "$comment": "Created an object for the identifier here to better handle requirements", + "type": "object", + "additionalProperties": false, + "properties": { + "publisherIdentifierValue": { + "$comment": "Made required here as part of the object", + "type": "string", + "minLength": 1, + "description": "Uniquely identifies the publisher, according to various schemes", + "examples": [ + "https://ror.org/04z8jg394" + ] + }, + "publisherIdentifierScheme": { + "$comment": "Made required here as part of the object", + "type": "string", + "minLength": 1, + "description": "The name of the publisher identifier scheme. If publisherIdentifier is used, publisherIdentifierScheme is mandatory", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the publisher identifier scheme", + "examples": [ + "https://ror.org/" + ] + } + }, + "required": [ + "publisherIdentifierValue", + "publisherIdentifierScheme" + ] + } + }, + "required": [ + "publisherName" + ] }, - "Size": { + "size": { "type": "array", - "description": "Size (e.g., bytes, pages, inches, etc.) or duration (extent), e.g., hours, minutes, days, etc., of a resource", + "description": "Size (e.g., bytes, pages, inches, etc.) relevant for the dataset", "items": { + "$comment": "This item and description are not in the DataCite Metadata Schema v4.5 but have been added to fit the JSON structure", "type": "string", "minLength": 1, "description": "A specific size item", - "examples": ["15 pages", "6 MB", "45 minutes"] + "examples": [ + "15 pages", + "6 MB", + "45 minutes" + ] }, "uniqueItems": true }, - "FundingReference": { + "fundingReference": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets. Examples have been adapted to suits clinical research datasets.", "type": "array", "description": "Information about financial support (funding) for the dataset", "items": { @@ -817,10 +1087,9 @@ "funderName": { "type": "string", "minLength": 1, - "description": "The name of the entity that provided the funding", + "description": "Name of the funding provider.", "examples": [ - "National Science Foundation (NSF)", - "European Commission (EC)" + "National Institutes of Health (NIH)" ] }, "funderIdentifier": { @@ -828,246 +1097,118 @@ "additionalProperties": false, "properties": { "funderIdentifierValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is from the DataCite 'funderIdentifier' key.", "type": "string", "minLength": 1, - "description": "Uniquely identifies a funding entity, according to various types." + "description": "Uniquely identifies a funding entity, according to various types.", + "examples": [ + "https://ror.org/01cwqze88" + ] }, "funderIdentifierType": { "type": "string", "minLength": 1, "description": "The type of funder identifier used.", - "enum": ["Crossref Funder ID", "GRID", "ISNI", "ROR", "Other"] + "enum": [ + "Crossref Funder ID", + "GRID", + "ISNI", + "ROR", + "Other" + ] }, "schemeURI": { "type": "string", "minLength": 1, - "description": "The URI of the funder identifier scheme or authority if one is used", + "description": "The URI of the funder identifier scheme", "examples": [ - "https://www.crossref.org/services/funder-registry/", "https://ror.org" ] } }, - "required": ["funderIdentifierValue"] + "required": [ + "funderIdentifierValue", + "funderIdentifierType" + ] }, "awardNumber": { "type": "object", "additionalProperties": false, "properties": { "awardNumberValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but has been added to fit the JSON structure. Description is from the DataCite 'awardNumber' key.", "type": "string", "minLength": 1, - "description": "The code assigned by the funder to a sponsored award", - "examples": ["GBMF3859.01"] + "description": "The code assigned by the funder to a sponsored award (grant).", + "examples": [ + "OT2OD032644" + ] }, "awardURI": { "type": "string", "minLength": 1, "description": "The URI leading to a page provided by the funder for more information about the award (grant).", "examples": [ - "https://www.moore.org/grants/list/GBMF3859.01", - "https://doi.org/10.35802/221400" + "https://reporter.nih.gov/search/VtCaq87pxkW1uosvSNPjHg/project-details/10858583" ] } }, - "required": ["awardNumberValue"] + "required": [ + "awardNumberValue" + ] }, "awardTitle": { "type": "string", "minLength": 1, - "description": "The title of the award (grant)", - "examples": ["The Moore-Sloan Data Science Environments"] + "description": "The human readable title or name of the award (grant)", + "examples": [ + "The awesome project of XYZ" + ] } }, - "required": ["funderName"] + "required": [ + "funderName" + ] }, "uniqueItems": true }, - "RelatedItem": { + "format": { + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to suit datasets", "type": "array", - "description": "Information about a resource related to the dataset, e.g., a journal or book of which the article or chapter is part. Can be used to provide series information or a text citation where the related resource does not have an identifier. However, it is also optional to provide an identifier here.", + "description": "Technical format of the data files in the dataset. Use file extension or MIME type where possible, e.g., PDF, XML, MPG or application/pdf, text/xml, video/mpeg.", "items": { - "type": "object", - "additionalProperties": false, - "description": "", - "properties": { - "relatedItemType": { - "$ref": "#/$defs/resourceItemType", - "description": "The type of the related item, e.g., journal article; book or chapter" - }, - "relationType": { - "$ref": "#/$defs/relationType", - "description": "The general type of the related resource." - }, - "relatedItemIdentifier": { - "type": "array", - "description": "The identifier for the related item.", - "items": { - "type": "object", - "description": "", - "additionalProperties": false, - "properties": { - "relatedItemIdentifierValue": { - "type": "string", - "minLength": 1, - "description": "The identifier for the related item." - }, - "relatedItemIdentifierType": { - "$ref": "#/$defs/identifierType", - "description": "The type of the related item identifier." - }, - "relatedMetadataScheme": { - "type": "string", - "minLength": 1, - "description": "The name of the scheme. Use only with this relationType pair: (HasMetadata/ IsMetadataFor)" - }, - "schemeURI": { - "type": "string", - "minLength": 1, - "description": "The URI of the relatedMetadataScheme. Use only with this relationType pair: (HasMetadata/ IsMetadataFor)" - }, - "schemeType": { - "type": "string", - "minLength": 1, - "description": "The type of the relatedMetadataScheme, linked with the schemeURI. Use only with this relationType pair: (HasMetadata/ IsMetadataFor)", - "examples": ["XSD", "DDT", "Turtle"] - } - }, - "required": ["relatedItemIdentifierValue"] - }, - "uniqueItems": true - }, - "creator": { - "type": "array", - "description": "The institution or person responsible for creating the related resource", - "items": { - "type": "object", - "additionalProperties": false, - "description": "", - "properties": { - "creatorName": { - "type": "string", - "minLength": 1, - "description": "The full name of the creator. Should be in the format: `family name, given name`. If the creator is an organization, the name should be in the format: `Organization name`." - }, - "nameType": { - "$ref": "#/$defs/typeOfNameOfPersonOrOrganization", - "description": "The type of name." - } - }, - "required": ["creatorName", "nameType"] - }, - "uniqueItems": true - }, - "title": { - "type": "array", - "items": { - "$ref": "#/$defs/titleItem" - }, - "description": "The main title of the item is mandatory. Others are optional", - "minItems": 1, - "uniqueItems": true - }, - "publicationYear": { - "$ref": "#/$defs/publicationYear", - "description": "The year when the item was or will be made publicly available" - }, - "volume": { - "type": "string", - "minLength": 1, - "description": "The volume of the related item." - }, - "issue": { - "type": "string", - "minLength": 1, - "description": "Issue number or name of the related item" - }, - "number": { - "type": "object", - "additionalProperties": false, - "description": "", - "properties": { - "numberValue": { - "type": "string", - "minLength": 1, - "description": "Number of the related item, e.g., report number of article number" - }, - "numberType": { - "type": "string", - "minLength": 1, - "description": "Type of the related item's number, e.g., report number or article number", - "enum": ["Article", "Chapter", "Report", "Other"] - } - }, - "required": ["numberValue"] - }, - "firstPage": { - "type": "string", - "minLength": 1, - "description": "First page of the related item, e.g., of the chapter, article, or conference paper in proceedings" - }, - "lastPage": { - "type": "string", - "minLength": 1, - "description": "Last page of the related item, e.g., of the chapter, article, or conference paper in proceedings" - }, - "publisher": { - "$ref": "#/$defs/publisher", - "description": "The name of the entity that holds, archives, publishes prints, distributes, releases, issues, or produces the resource." - }, - "edition": { - "type": "string", - "minLength": 1, - "description": "The edition of the related item, e.g., the edition of a book" - }, - "contributor": { - "type": "array", - "description": "The institution or person responsible for contributing to the related resource", - "items": { - "type": "object", - "additionalProperties": false, - "description": "", - "properties": { - "contributorType": { - "$ref": "#/$defs/contributorType", - "description": "The type of contributor of the resource" - }, - "contributorName": { - "type": "string", - "minLength": 1, - "description": "The full name of the contributor. Should be in the format: `family name, given name`. If the contributor is an organization, the name should be in the format: `Organization name`." - }, - "nameType": { - "$ref": "#/$defs/typeOfNameOfPersonOrOrganization", - "description": "The type of name." - } - }, - "required": ["contributorName", "contributorType"] - }, - "uniqueItems": true - } - }, - "required": ["relatedItemType", "relationType"] + "type": "string" }, - "uniqueItems": true + "uniqueItems": true, + "examples": [ + "PDF", + "XML", + "MPG", + "application/pdf", + "text/xml", + "video/mpeg" + ] } }, "required": [ - "Identifier", - "Title", - "Creator", - "PublicationYear", - "ResourceType", - "DatasetRecordKeys", - "DatasetDeIdentLevel", - "DatasetConsent", - "ManagingOrganisation", - "AccessType", - "AccessDetails", - "Publisher" + "schema", + "identifier", + "title", + "version", + "creator", + "publicationYear", + "resourceType", + "datasetDeIdentLevel", + "datasetConsent", + "managingOrganization", + "accessType", + "accessDetails", + "rights", + "publisher" ], - "$defs": { + "definitions": { "identifierType": { + "$comment": "The options and their description are exactly from DataCite Metadata Schema v4.5 extended with the 'Other' option from the 'object_identifiers' in the ECRIN Metadata Schema v6.0 for data object", "type": "string", "oneOf": [ { @@ -1147,7 +1288,7 @@ "description": "Permanent identifier for Web applications. Mostly used to publish vocabularies and ontologies. The letters `w3` stand for `World Wide Web`." }, { - "const": "other", + "const": "Other", "description": "None of the listed identifier types." } ] @@ -1157,39 +1298,45 @@ "additionalProperties": false, "properties": { "titleValue": { + "$comment": "This key is not in the DataCite Metadata Schema v4.5 but been added to fit the JSON structure. Description is based on the DataCite Metadata Schema v4.5 for 'title' but modified to suit datasets.", "type": "string", "minLength": 1, - "description": "The name by which the dataset is known." + "description": "A name or title by which the dataset is known." }, "titleType": { - "$ref": "#/$defs/titleType", - "description": "Empty if titleValue is the main tile. Must be from the controlled values of titleType otherwise." + "$comment": "Description is based on the DataCite Metadata Schema v4.5 but modified to for more clarity.", + "$ref": "#/definitions/titleType", + "description": "The titleType subproperty is used when more than a single title is provided. Unless otherwise indicated by titleType, a title is considered to be the main title. Must be from the controlled values of titleType otherwise." } }, - "required": ["titleValue"] + "required": [ + "titleValue" + ] }, "titleType": { + "$comment": "The options are from the DataCite Metadata schema v4.5 but descriptions are added since they are not provided by in the DataCite schema.", "type": "string", "oneOf": [ { "const": "AlternativeTitle", - "description": "" + "description": "An alternate name for the dataset other than the main title" }, { "const": "Subtitle", - "description": "A subtitle provided by object creators or study sponsors." + "description": "A subtitle for the dataset." }, { "const": "TranslatedTitle", - "description": "Used in conjunction with language code to indicate language translated into." + "description": "Translated version of the main title in a different language" }, { + "$comment": "Description is from the ECRIM Metadata Schema for data object v6.0", "const": "Other", "description": "Any alternative title not described elsewhere." } ] }, - "typeOfNameOfPersonOrOrganization": { + "nameType": { "type": "string", "oneOf": [ { @@ -1203,6 +1350,7 @@ ] }, "contributorType": { + "$comment": "The options and their descriptions are exactly from DataCite Metadata Schema v4.5 extended with the options from the 'object_contributors' in the ECRIN Metadata schema v6.0 for data object. ECRIN options have been Pascal Cased to align with DataCite options.", "type": "string", "oneOf": [ { @@ -1263,7 +1411,7 @@ }, { "const": "Researcher", - "description": "A person involved in analysing data or the results of an experiment or formal study. May indicate an intern or assistant to one of the authors who helped with research but who was not so `key” as `o be listed as an author." + "description": "A person involved in analysing data or the results of an experiment or formal study. May indicate an intern or assistant to one of the authors who helped with research but who was not so `key\u201d as `o be listed as an author." }, { "const": "ResearchGroup", @@ -1290,90 +1438,112 @@ "description": "Any person or institution making a significant contribution to the development and/or maintenance of the resource, but whose contribution is not adequately described by any of the other values for contributorType" }, { - "const": "Study lead", + "$comment": "From ECRIN", + "const": "StudyLead", "description": "The individual who, if not the sponsor themselves, leads and co-ordinates the scientific and clinical activity within a clinical study, including co-ordinating the work of principal investigators at clinical sites. May be known as the Co-ordinating Investigator, the Study Chair, Study Director or similar terms." }, { + "$comment": "From ECRIN", "const": "CTSitePrincipalInvestigator", "description": "The individual responsible for the safe conduct of a clinical trial at a particular clinical site." }, { + "$comment": "From ECRIN", "const": "ClinicalStudyManager", "description": "An individual responsible for the operational management of a clinical study. Similar to a Project Manager but a study manager is heavily involved in the management of data and data collection." }, { + "$comment": "From ECRIN", "const": "TrialSponsor", "description": "The organisation or individual that has the formal, legal role of a clinical trial sponsor, and is legally responsible for all aspects of a clinical trial." }, { + "$comment": "From ECRIN", "const": "SponsorContact", "description": "An individual representing the sponsor and acting as an initial contact point." }, { + "$comment": "From ECRIN", "const": "PublicContact", "description": "An individual designated as dealing with non-scientific queries from the public or press." }, { + "$comment": "From ECRIN", "const": "RecruitmentContact", "description": "An individual designated as providing periodic updates on recruitment information or status, at all sites, usually for monitoring purposes." }, { + "$comment": "From ECRIN", "const": "StudyFunder", "description": "An organisation providing some or all of the additional funds required for the study." }, { + "$comment": "From ECRIN", "const": "FunderContact", "description": "An individual representing the funder and acting as an initial contact point." }, { + "$comment": "From ECRIN", "const": "IndependentMonitoringCommitteeMember", "description": "A member of a safety monitoring committee for a clinical trial, independent of the researchers and research activity." }, { + "$comment": "From ECRIN", "const": "MedicinalProductSupplier", "description": "Organisation that provides one or more of the medicines investigated in a clinical study." }, { + "$comment": "From ECRIN", "const": "MedicalDeviceSupplier", "description": "Organisation that provides one or more of the medical devices in a clinical study." }, { + "$comment": "From ECRIN", "const": "LogisticsSupportOrganisation", "description": "Organisation that provides logistical input, e.g. provides a drug distribution service." }, { + "$comment": "From ECRIN", "const": "ScientificSupportOrganisation", "description": "Organisation that provides scientific support, e.g. a national or international research network." }, { + "$comment": "From ECRIN", "const": "CentralLaboratory", "description": "Organisation that provides a central specialist laboratory testing facility.." }, { + "$comment": "From ECRIN", "const": "CentralImagingFacility", "description": "Organisation that provides a central specialist imaging or scanning facility." }, { + "$comment": "From ECRIN", "const": "ClinicalOrganisation", "description": "Organisation, usually a primary or secondary health care organisation, that manages one or more of the sites where a clinical study takes place." }, { + "$comment": "From ECRIN", "const": "ClinicalSite", "description": "Organisation or location, usually in a primary or secondary health care organisation, that is one of the sites where a clinical study takes place." }, { + "$comment": "From ECRIN", "const": "CollaboratingOrganisation", "description": "May be listed as a secondary sponsor, an organisation other than the lead sponsor involved in supporting a study." }, { + "$comment": "From ECRIN", "const": "SponsorInvestigator", "description": "An individual with the role of sponsor as well as being the co-ordinating investigator for the study." }, { + "$comment": "From ECRIN", "const": "ResultsContact", "description": "The individual, occasionally organisation, to be contacted for further information on the study results." }, { + "$comment": "From ECRIN", "const": "ResearchGroupMember", "description": "From PubMed, an 'investigator' is an individual (e.g., collaborator or investigator) who is not an author of a paper but is listed as a member of a collective/corporate group that is an author of the paper." } @@ -1472,7 +1642,7 @@ }, { "const": "Software", - "description": "A computer program other than a computational notebook, in either source code (text) or compiled form. Use this type for general software components supporting scholarly research. Use the “ComputationalNoteb ook” value for virtual notebooks." + "description": "A computer program other than a computational notebook, in either source code (text) or compiled form. Use this type for general software components supporting scholarly research. Use the \u201cComputationalNoteb ook\u201d value for virtual notebooks." }, { "const": "Sound", @@ -1480,7 +1650,7 @@ }, { "const": "Standard", - "description": "Something established by authority, custom, or general consent as a model, example, or point of reference" + "description": "Something established by authority, custom, or general consent as a model, example, or point of reference" }, { "const": "Text", @@ -1498,127 +1668,127 @@ }, "relationType": { "type": "string", - "description": "Description of the relationship of the resource being registered (A) and the related resource (B).", + "description": "Description of the relationship of the dataset (A) and the related resource (B).", "oneOf": [ { "const": "IsCitedBy", - "description": "indicates that B includes A in a citation" + "description": "Indicates that B includes A in a citation" }, { "const": "Cites", - "description": "indicates that A includes B in a citation" + "description": "Indicates that A includes B in a citation" }, { "const": "IsSupplementTo", - "description": "indicates that A is a supplement to B" + "description": "Indicates that A is a supplement to B" }, { "const": "IsSupplementedBy", - "description": "indicates that B is a supplement to A" + "description": "Indicates that B is a supplement to A" }, { "const": "IsContinuedBy", - "description": "indicates A is continued by the work B" + "description": "Indicates A is continued by the work B" }, { "const": "Continues", - "description": "indicates A is a continuation of the work B" + "description": "Indicates A is a continuation of the work B" }, { "const": "Describes", - "description": "indicates A describes B" + "description": "Indicates A describes B" }, { "const": "IsDescribedBy", - "description": "indicates A is described by B" + "description": "Indicates A is described by B" }, { "const": "HasMetadata", - "description": "indicates resource A has additional metadata B" + "description": "Indicates resource A has additional metadata B" }, { "const": "IsMetadataFor", - "description": "indicates additional metadata A for a resource B" + "description": "Indicates additional metadata A for a resource B" }, { "const": "HasVersion", - "description": "indicates A has a version (B)" + "description": "Indicates A has a version (B)" }, { "const": "IsVersionOf", - "description": "indicates A is a version of B" + "description": "Indicates A is a version of B" }, { "const": "IsNewVersionOf", - "description": "indicates A is a new edition of B, where the new edition has been modified or updated" + "description": "Indicates A is a new edition of B, where the new edition has been modified or updated" }, { "const": "IsPreviousVersionOf", - "description": "indicates A is a previous edition of B" + "description": "Indicates A is a previous edition of B" }, { "const": "IsPartOf", - "description": "indicates A is a portion of B; may be used for elements of a series" + "description": "Indicates A is a portion of B; may be used for elements of a series" }, { "const": "HasPart", - "description": "indicates A includes the part B" + "description": "Indicates A includes the part B" }, { "const": "IsPublishedIn", - "description": "indicates A is published inside B, but is independent of other things published inside of B" + "description": "Indicates A is published inside B, but is independent of other things published inside of B" }, { "const": "IsReferencedBy", - "description": "indicates A is used as a source of information by B" + "description": "Indicates A is used as a source of information by B" }, { "const": "References", - "description": "indicates B is used as a source of information for A" + "description": "Indicates B is used as a source of information for A" }, { "const": "IsDocumentedBy", - "description": "indicates B is documentation about/ explaining A; e.g. points to software documentation" + "description": "Indicates B is documentation about/ explaining A; e.g. points to software documentation" }, { "const": "Documents", - "description": "indicates A is documentation about B; e.g. points to software documentation" + "description": "Indicates A is documentation about B; e.g. points to software documentation" }, { "const": "IsCompiledBy", - "description": "indicates B is used to compile or create A" + "description": "Indicates B is used to compile or create A" }, { "const": "Compiles", - "description": "indicates B is the result of a compile or creation event using A" + "description": "Indicates B is the result of a compile or creation event using A" }, { "const": "IsVariantFormOf", - "description": "indicates A is a variant or different form of B" + "description": "Indicates A is a variant or different form of B" }, { "const": "IsOriginalFormOf", - "description": "indicates A is the original form of B" + "description": "Indicates A is the original form of B" }, { "const": "IsIdenticalTo", - "description": "indicates that A is identical to B, for use when there is a need to register two separate instances of the same resource" + "description": "Indicates that A is identical to B, for use when there is a need to register two separate instances of the same resource" }, { "const": "IsReviewedBy", - "description": "indicates that A is reviewed by B" + "description": "Indicates that A is reviewed by B" }, { "const": "Reviews", - "description": "indicates that A is a review of B" + "description": "Indicates that A is a review of B" }, { "const": "IsDerivedFrom", - "description": "indicates B is a source upon which A is based" + "description": "Indicates B is a source upon which A is based" }, { "const": "IsSourceOf", - "description": "indicates A is a source upon which B is based" + "description": "Indicates A is a source upon which B is based" }, { "const": "IsRequiredBy", @@ -1635,6 +1805,14 @@ { "const": "IsObsoletedBy", "description": "Indicates A is replaced by B" + }, + { + "const": "IsCollectedBy", + "description": "Indicates A is collected by B" + }, + { + "const": "Collects", + "description": "Indicates A collects B" } ] }, @@ -1642,17 +1820,9 @@ "type": "string", "minLength": 4, "maxLength": 4, - "examples": ["2018"] - }, - "publisher": { - "type": "string", - "minLength": 1, "examples": [ - "World Data Center for Climate (WDCC)", - "GeoForschungsZentrum Potsdam (GFZ)", - "Geological Institute, University of Tokyo", - "GitHub" + "2022" ] } } -} +} \ No newline at end of file diff --git a/pyfairdatatools/schemas/datatype_dictionary.schema.json b/pyfairdatatools/schemas/datatype_dictionary.schema.json new file mode 100644 index 0000000..6aec62f --- /dev/null +++ b/pyfairdatatools/schemas/datatype_dictionary.schema.json @@ -0,0 +1,224 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schema.aireadi.org/files/datatype_dictionary.json", + "title": "Datatype dictionary", + "description": "This is the schema for the datatype_dictionary.json metadata file from the Clinical Dataset Structure (CDS)", + "type": "object", + "properties": { + "datatype": { + "type": "array", + "additionalProperties": false, + "items": { + "type": "object", + "properties": { + "code_name": { + "type": "string", + "description": "Main name used to refer to the datatype. Must use lower case alphanumerical and use underscore for white space (snake_case).", + "pattern": "[a-zA-Z]+(_[a-zA-Z]+)*" + }, + "datatype_description": { + "type": "object", + "properties": { + "description_text": { + "type": "string", + "description": "Brief text that explains what the datatype is. Specify what type of files are expected, what device(s) or platform(s) they are typically collecting with, etc." + }, + "description_source": { + "type": "object", + "description": "Information about the resource/person/organization that provided the description text.", + "properties": { + "resource": { + "type": "object", + "properties": { + "resource_name": { + "type": "string", + "description": "Name of the resource" + }, + "resource_links": { + "type": "array", + "description": "URL(s) that provides additional information about the organization, e.g. website of the organization.", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "resource_name" + ] + }, + "organization": { + "type": "object", + "properties": { + "organization_name": { + "type": "string", + "description": "Name of the organization" + }, + "rorid": { + "type": "string", + "description": "Research Organization Registry (ROR) ID (https://ror.org/) of the organization" + }, + "organization_links": { + "type": "array", + "description": "URL(s) that provides additional information about the organization, e.g. website of the organization.", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "organization_name" + ] + }, + "person": { + "type": "object", + "properties": { + "person_name": { + "type": "string", + "description": "Name of the person" + }, + "orcid": { + "type": "string", + "description": "ORCID iD (https://orcid.org/) of the person" + }, + "person_links": { + "type": "array", + "description": "URL(s) that provides additional information about the person, e.g. website of the person.", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "person_name" + ] + }, + "comment": { + "type": "string", + "description": "Details about how the description was established, e.g., link to resources that insipired the description." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "resource" + ] + }, + { + "required": [ + "organization" + ] + }, + { + "required": [ + "person" + ] + } + ] + } + }, + "additionalProperties": false, + "required": [ + "description_text", + "description_source" + ] + }, + "aliases": { + "type": "array", + "description": "Alternate name(s) for the datatype. Must use lower case alphanumerical and use underscore for white space (snake_case).", + "items": { + "type": "string", + "pattern": "[a-zA-Z]+(_[a-zA-Z]+)*" + } + }, + "related_terms": { + "type": "object", + "description": "IDs or links of related terms found in well established ontologies and dictionaries such as the Medical Subject Headings (MeSH, https://meshb.nlm.nih.gov/) and the National Cancer Institute (NCIT) Thesaurus (https://ncit.nci.nih.gov/ncitbrowser).", + "properties": { + "ncit": { + "type": "array", + "description": "NCI Thesaurus (NCIt) ID(s) of related term(s) (https://ncithesaurus.nci.nih.gov/ncitbrowser/).", + "items": { + "type": "string" + } + }, + "mesh": { + "type": "array", + "description": "Medical Subject Headings (MeSH) ID of a related term (https://meshb.nlm.nih.gov/).", + "items": { + "type": "string" + } + }, + "other": { + "type": "array", + "description": "Link(s) to other related term(s)", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "ncit" + ] + }, + { + "required": [ + "mesh" + ] + }, + { + "required": [ + "other" + ] + } + ] + }, + "related_standards": { + "type": "array", + "description": "Standards that are relevant to this data type for organizing data files, selecting file format, including metadata, etc.", + "items": { + "type": "object", + "properties": { + "standard_name": { + "type": "string", + "description": "Name of the standard" + }, + "standard_reference": { + "type": "string", + "description": "Main reference providing additional information about the standard" + }, + "standard_description": { + "type": "string", + "description": "Description of the standard. Explain what this standard is for (organizing data files, selecting file format, including metadata, etc.)." + }, + "standard_resources": { + "type": "array", + "description": "Link(s) to additional resources for learning about or implementing the standard", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "standard_name", + "standard_reference" + ] + } + } + }, + "additionalProperties": false, + "required": [ + "code_name", + "datatype_description" + ] + } + } + } +} \ No newline at end of file diff --git a/pyfairdatatools/schemas/participants.schema.json b/pyfairdatatools/schemas/participants.schema.json index 5bea664..4ffaff1 100644 --- a/pyfairdatatools/schemas/participants.schema.json +++ b/pyfairdatatools/schemas/participants.schema.json @@ -1,7 +1,7 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schema.aireadi.org/files/participants.json", - "title": "README", + "title": "Participants", "description": "Additional text here", "type": "array", "items": { diff --git a/pyfairdatatools/schemas/study_description.schema.json b/pyfairdatatools/schemas/study_description.schema.json index 2bd426f..32e627b 100644 --- a/pyfairdatatools/schemas/study_description.schema.json +++ b/pyfairdatatools/schemas/study_description.schema.json @@ -1,135 +1,276 @@ { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://schema.aireadi.org/files/study_description.json", + "$id": "https://schema.aireadi.org/v0.1.0/study_description.json", + "$schema": "http://json-schema.org/draft-07/schema", "title": "Study Description", - "description": "Add a description of the study and the dataset.", + "description": "This is the schema for the study_description.json metadata file from the Clinical Dataset Structure (CDS). It is based on the ClinicalTrials.gov study protocol registration schema, unless specified otherwise in $comment. The keys are based on the the Clinicaltrials.gov JSON study record (https://classic.clinicaltrials.gov/api/info/study_structure?fmt=JSON) where we kept only the keys relevant to the study protocol registration as per the Clinicaltrials.gov Data Elements (https://prsinfo.clinicaltrials.gov/definitions.html). The descriptions, requirements, and controlled lists are based on the Clinicaltrials.gov Data Elements (https://prsinfo.clinicaltrials.gov/definitions.html) and extended with the ClinicalTrials.gov XML schema descriptor (https://prsinfo.clinicaltrials.gov/ProtocolRecordSchema.xsd) when necessary. Character limits have been removed unless otherwise specified. Note that the 'BriefTitle', 'OutcomesModule', 'IPDSharingStatementModule', and 'ReferencesModule' properties from ClinicalTrials.gov are not included as they were not deemed relevant for the use case in the CDS. Some keys, values in controlled lists, etc. are from the the ECRIN Metadata Schema for study v6.0. We have also introduced some modifications as necessary for tailoring the schema to clinical research datasets. All keys are camelCase.", "type": "object", "additionalProperties": false, "properties": { - "IdentificationModule": { + "schema": { + "description": "Link to the schema to be included so that users of the resulting JSON file can find the related schema easily", + "type": "string", + "const": "https://schema.aireadi.org/v0.1.0/study_description.json" + }, + "identificationModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#identification", "type": "object", "additionalProperties": false, "properties": { - "OrgStudyIdInfo": { + "officialTitle": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", + "type": "string", + "description": "The title of the clinical study" + }, + "acronym": { + "type": "string", + "description": "An acronym or abbreviation used publicly to identify the clinical study, if any" + }, + "orgStudyIdInfo": { "type": "object", "additionalProperties": false, "properties": { - "OrgStudyId": { + "orgStudyId": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "string", "description": "Main unique identifier assigned to the study.", "minLength": 1 }, - "OrgStudyIdType": { - "$ref": "#/$defs/studyIdType", + "orgStudyIdType": { + "$comment": "Description has been added here (based on SecondaryIdType) since this property is included in the ClinicalTrials.gov JSON study record but not in the Data Elements", + "$ref": "#/definitions/studyIdType", "description": "A description of the type of main ID." }, - "OrgStudyIdDomain": { + "orgStudyIdDomain": { + "$comment": "Description has been added here (based on SecondaryIdDomain) since this property is included in the ClinicalTrials.gov JSON study record but not in the Data Elements", "type": "string", - "description": "If an ID Type of 'Other Grant/Funding Number', 'Registry Identifier', or 'Other Identifier' is selected, provide the name of the funding organization, clinical trial registry, or organization that issued the identifier. (required if ID Type of 'Other Grant/Funding Number', 'Registry Identifier', or 'Other Identifier' is selected)", + "description": "If an ID Type of 'Other Grant/Funding Number', 'Registry Identifier', or 'Other Identifier' is selected, provide the name of the funding organization, clinical trial registry, or organization that issued the identifier", "minLength": 1 }, - "OrgStudyIdLink": { + "orgStudyIdLink": { + "$comment": "Description has been added here (based on SecondaryIdLink) since this property is included in the ClinicalTrials.gov JSON study record but not in the Data Elements", "type": "string", + "description": "If the ID has a resolvable link, optionally provide the full link here. For instance, if ID is 'K01HL147713' then the ID link is 'https://reporter.nih.gov/quickSearch/K01HL147713'", "format": "uri", "minLength": 1 } }, - "required": ["OrgStudyId", "OrgStudyIdType"] + "required": [ + "orgStudyId", + "orgStudyIdType" + ], + "if": { + "properties": { + "orgStudyIdType": { + "enum": [ + "Other Grant/Funding Number", + "Registry Identifier", + "Other Identifier" + ] + } + } + }, + "then": { + "required": [ + "orgStudyIdDomain" + ] + } }, - "SecondaryIdInfoList": { + "secondaryIdInfoList": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { - "SecondaryId": { + "secondaryId": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "string", - "description": "An identifier(s) (ID), if any, other than the main identifier.", + "description": "An identifier, if any, other than the main identifier.", "minLength": 1 }, - "SecondaryIdType": { - "$ref": "#/$defs/studyIdType", + "secondaryIdType": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", + "$ref": "#/definitions/studyIdType", "description": "A description of the type of secondary ID." }, - "SecondaryIdDomain": { + "secondaryIdDomain": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "string", - "description": "If an ID Type of 'Other Grant/Funding Number,' 'Registry Identifier,' or 'Other Identifier' is selected, provide the name of the funding organization, clinical trial registry, or organization that issued the identifier. (required if Secondary ID Type of 'Other Grant/Funding Number', 'Registry Identifier', or 'Other Identifier' is selected)", + "description": "If an ID Type of 'Other Grant/Funding Number,' 'Registry Identifier,' or 'Other Identifier' is selected, provide the name of the funding organization, clinical trial registry, or organization that issued the identifier.", "minLength": 1 }, - "SecondaryIdLink": { + "secondaryIdLink": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "string", "format": "uri", "description": "If the ID has a resolvable link, optionally provide the full link here. For instance, if ID is 'K01HL147713' then the ID link is 'https://reporter.nih.gov/quickSearch/K01HL147713'", "minLength": 1 } }, - "required": ["SecondaryId", "SecondaryIdType"] + "required": [ + "secondaryId", + "secondaryIdType" + ], + "if": { + "properties": { + "secondaryIdType": { + "enum": [ + "Other Grant/Funding Number", + "Registry Identifier", + "Other Identifier" + ] + } + } + }, + "then": { + "required": [ + "secondaryIdDomain" + ] + } }, "minItems": 1, "uniqueItems": true } }, - "required": ["OrgStudyIdInfo"] + "required": [ + "orgStudyIdInfo" + ] }, - "StatusModule": { + "statusModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#status", "type": "object", "additionalProperties": false, "properties": { - "OverallStatus": { - "$ref": "#/$defs/statusOptions", + "overallStatus": { + "$ref": "#/definitions/statusOptions", "description": "The recruitment status for the clinical study as a whole, based upon the status of the individual sites. If at least one facility in a multi-site clinical study has an Individual Site Status of 'Recruiting', then the Overall Recruitment Status for the study must be 'Recruiting'." }, - "WhyStopped": { + "whyStopped": { "type": "string", - "description": "A brief explanation of the reason(s) why such clinical study was stopped (for a clinical study that is 'Suspended', 'Terminated', or 'Withdrawn' prior to its planned completion as anticipated by the protocol). Required if OverallStatus is 'Suspended', 'Terminated', or 'Withdrawn'", + "description": "A brief explanation of the reason(s) why such clinical study was stopped (for a clinical study that is 'Suspended', 'Terminated', or 'Withdrawn' prior to its planned completion as anticipated by the protocol)", "minLength": 1 }, - "StartDateStruct": { + "startDateStruct": { "type": "object", "additionalProperties": false, "description": "The estimated date on which the clinical study will be open for recruitment of participants, or the actual date on which the first participant was enrolled. Note: 'Enrolled' means a participant's, or their legally authorized representative's, agreement to participate in a clinical study following completion of the informed consent process. Potential participants who are screened for the purpose of determining eligibility for the study, but do not participate in the study, are not considered enrolled, unless otherwise specified by the protocol.", "properties": { - "StartDate": { + "startDate": { + "$comment": "The date format is from the XML schema descriptor. This has been added here in the description.", "type": "string", - "description": "Format like 'June 12, 2023'", + "description": "Format must be 'YYYY-MM'", + "format": "date", "minLength": 1 }, - "StartDateType": { + "startDateType": { + "$comment": "Description added here", + "description": "Specify if the start date is actual or anticipated", "type": "string", - "enum": ["Actual", "Anticipated"] + "enum": [ + "Actual", + "Anticipated" + ] } }, - "required": ["StartDate", "StartDateType"] + "required": [ + "startDate", + "startDateType" + ] }, - "CompletionDateStruct": { + "completionDateStruct": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "object", "additionalProperties": false, - "description": "The date the final participant was examined or received an intervention for purposes of final collection of data (for example, last participant's last visit), whether the clinical study concluded according to the pre-specified protocol or was terminated.", + "description": "The date the final participant was examined or received an intervention for purposes of final collection of data (for example, last participant's last visit), whether the clinical study concluded according to the pre-specified protocol or was terminated. If the study is not completed yet, an anticipated date can be provided.", "properties": { - "CompletionDate": { + "completionDate": { + "$comment": "The date format is from the XML schema descriptor. This has been added here in the description.", "type": "string", - "description": "Format like 'June 12, 2023'", + "description": "Format must be 'YYYY-MM'", + "format": "date", "minLength": 1 }, - "CompletionDateType": { + "completionDateType": { + "$comment": "Description added here", + "description": "Specify if the start date is actual or anticipated", "type": "string", - "enum": ["Actual", "Anticipated"] + "enum": [ + "Actual", + "Anticipated" + ] } }, - "required": ["CompletionDate", "CompletionDateType"] + "required": [ + "completionDate", + "completionDateType" + ] } }, - "required": ["OverallStatus", "StartDateStruct"] + "required": [ + "overallStatus", + "startDateStruct", + "completionDateStruct" + ] }, - "SponsorCollaboratorsModule": { + "sponsorCollaboratorsModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#sponsors", "type": "object", "additionalProperties": false, "properties": { - "ResponsibleParty": { + "leadSponsor": { "type": "object", "additionalProperties": false, "properties": { - "ResponsiblePartyType": { + "leadSponsorName": { + "type": "string", + "description": "The name of the entity or the individual who is the sponsor of the clinical study. Note: When a clinical study is conducted under an investigational new drug application (IND) or investigational device exemption (IDE), the IND or IDE holder is considered the sponsor. When a clinical study is not conducted under an IND or IDE, the single person or entity who initiates the study, by preparing and/or planning the study, and who has authority and control over the study, is considered the sponsor.", + "minLength": 1 + }, + "leadSponsorIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify sponsor and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "leadSponsorIdentifierValue": { + "type": "string", + "description": "Uniquely identifies sponsor, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "leadSponsorIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "leadSponsorIdentifierValue", + "leadSponsorIdentifierScheme" + ] + } + }, + "required": [ + "leadSponsorName" + ] + }, + "responsibleParty": { + "type": "object", + "additionalProperties": false, + "properties": { + "responsiblePartyType": { + "description": "An indication of whether the responsible party is the sponsor, the sponsor-investigator, or a principal investigator designated by the sponsor to be the responsible party. The sponsor may designate a principal investigator as the responsible party if such principal investigator meets all of the following requirements: is responsible for conducting the study; has access to and control over the data from the study; has the right to publish the results of the study; and has the ability to meet all of the requirements for submitting and updating clinical study information.", "type": "string", "oneOf": [ { @@ -146,121 +287,426 @@ } ] }, - "ResponsiblePartyInvestigatorFullName": { + "responsiblePartyInvestigatorFirstName": { + "$comment": "Name split into first and last here", "type": "string", - "description": "Name of the investigator, including first and last name. (required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator')", + "description": "First name of the investigator. Required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator'", "minLength": 1, - "examples": ["John Smith"] + "examples": [ + "James" + ] }, - "ResponsiblePartyInvestigatorTitle": { + "responsiblePartyInvestigatorLastName": { + "$comment": "Name split into first and last here", "type": "string", - "description": "Professional title of the investigator (for example, Professor of Medicine). (required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator')", + "description": "Last name of the investigator. Required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator'", "minLength": 1, - "examples": ["Professor of Medicine"] + "examples": [ + "Smith" + ] }, - "ResponsiblePartyInvestigatorAffiliation": { + "responsiblePartyInvestigatorTitle": { "type": "string", - "description": "Name of the organization to which the investigator is affiliated. (required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator')", + "description": "The official title of the investigator at the primary organizational affiliation (required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator')", "minLength": 1, - "examples": ["University of California, San Diego"] + "examples": [ + "Professor of Medicine" + ] + }, + "responsiblePartyInvestigatorIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify the investigator and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "array", + "description": "Uniquely identifies an investigator, according to various schemes.", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "responsiblePartyInvestigatorIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies an investigator.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427" + ] + }, + "responsiblePartyInvestigatorIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the name identifier scheme.", + "examples": [ + "ORCID" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://orcid.org" + ] + } + }, + "required": [ + "responsiblePartyInvestigatorIdentifierValue", + "responsiblePartyInvestigatorIdentifierScheme" + ] + }, + "uniqueItems": true + }, + "responsiblePartyInvestigatorAffiliation": { + "$comment": "Made into an object. Description is based on the ClinicalTrials.gov Data Elements but modified for clarity ('investigator' used instead of 'individual')", + "description": "Primary organizational affiliation of the investigator (required if ResponsiblePartyType is 'Principal Investigator' or 'Sponsor-Investigator')", + "type": "object", + "additionalProperties": false, + "properties": { + "responsiblePartyInvestigatorAffiliationName": { + "$comment": "Key added to fit the name in the object", + "type": "string", + "description": "The name of the affiliation of the investigator", + "minLength": 1, + "examples": [ + "University of California, San Diego" + ] + }, + "responsiblePartyInvestigatorAffiliationIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify sponsor and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "responsiblePartyInvestigatorAffiliationIdentifierValue": { + "type": "string", + "description": "Uniquely identifies affiliation, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "responsiblePartyInvestigatorAffiliationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "responsiblePartyInvestigatorAffiliationIdentifierValue", + "responsiblePartyInvestigatorAffiliationIdentifierScheme" + ] + } + }, + "required": [ + "responsiblePartyInvestigatorAffiliationName" + ] } }, - "required": ["ResponsiblePartyType"] - }, - "LeadSponsor": { - "type": "object", - "additionalProperties": false, - "properties": { - "LeadSponsorName": { - "type": "string", - "description": "The name of the entity or the individual who is the sponsor of the clinical study. Note: When a clinical study is conducted under an investigational new drug application (IND) or investigational device exemption (IDE), the IND or IDE holder is considered the sponsor. When a clinical study is not conducted under an IND or IDE, the single person or entity who initiates the study, by preparing and/or planning the study, and who has authority and control over the study, is considered the sponsor.", - "minLength": 1 + "required": [ + "responsiblePartyType" + ], + "if": { + "properties": { + "responsiblePartyType": { + "enum": [ + "Principal Investigator", + "Sponsor-Investigator" + ] + } } }, - "required": ["LeadSponsorName"] + "then": { + "required": [ + "responsiblePartyInvestigatorFirstName", + "responsiblePartyInvestigatorLastName", + "responsiblePartyInvestigatorTitle", + "responsiblePartyInvestigatorAffiliation" + ] + } }, - "CollaboratorList": { + "collaboratorList": { "type": "array", "description": "Other organizations (if any) providing support. Support may include funding, design, implementation, data analysis or reporting. The responsible party is responsible for confirming all collaborators before listing them.", "items": { "type": "object", "additionalProperties": false, "properties": { - "CollaboratorName": { + "collaboratorName": { + "$comment": "Description added here since the ClinicalTrials.gov Data Elements document only provide a high-level description of the collaborators", "type": "string", - "description": "The name of the entity or the individual who is the collaborator of the clinical study." + "description": "The name of the collaborating organization" + }, + "collaboratorNameIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify collaborator and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "collaboratorNameIdentifierValue": { + "type": "string", + "description": "Uniquely identifies the collaborating organization, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "collaboratorNameIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "collaboratorNameIdentifierValue", + "collaboratorNameIdentifierScheme" + ] } }, - "required": ["CollaboratorName"] + "required": [ + "collaboratorName" + ] }, "minItems": 1, "uniqueItems": true } }, - "required": ["ResponsibleParty", "LeadSponsor"] + "required": [ + "leadSponsor", + "responsibleParty" + ] }, - "OversightModule": { + "oversightModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#oversight. 'Device Product Not Approved or Cleared by U.S. FDA', 'Post Prior to U.S. FDA Approval or Clearance', 'Pediatric Postmarket Surveillance of a Device Product', 'Investigational New Drug Application (IND)/Investigational Device Exemption (IDE) Information' (and subitems), and 'Product Manufactured in and Exported from the U.S.' Data Elements were not kept here as they were deemed not relevant for datasets. ", "type": "object", "additionalProperties": false, "properties": { - "OversightHasDMC": { + "isFDARegulatedDrug": { + "type": "string", + "description": "Indication that a clinical study is studying a drug product (including a biological product) subject to section 505 of the Federal Food, Drug, and Cosmetic Act or to section 351 of the Public Health Service Act.", + "enum": [ + "Yes", + "No" + ] + }, + "isFDARegulatedDevice": { + "type": "string", + "description": "Indication that a clinical study is studying a device product subject to section 510(k), 515, or 520(m) of the Federal Food, Drug, and Cosmetic Act.", + "enum": [ + "Yes", + "No" + ] + }, + "humanSubjectReviewStatus": { + "$comment": "This key is not in the ClinicalTrials.gov JSON study record but it has been added here to match the corresponding the Data Elements. 'Board Approval Number', 'Board Name', 'Board Affiliation', and 'Board Contact' Data Elements were not kept here as they were deemed not relevant for datasets.", + "description": "Indicate whether a clinical study has been reviewed and approved by at least one human subjects protection review board or such review is not required per applicable law (for example, 21 CFR Part 56, 45 CFR Part 46, or other applicable regulation)", + "$ref": "#/definitions/humanSubjectReviewStatus" + }, + "oversightHasDMC": { "type": "string", - "description": "Indicate whether a data monitoring committee has been appointed for this study. The data monitoring committee (board) is a group of independent scientists who are appointed to monitor the safety and scientific integrity of a human research intervention, and to make recommendations to the sponsor regarding the stopping of the trial for efficacy, for harms or for futility. The composition of the committee is dependent upon the scientific skills and knowledge required for monitoring the particular study. Select Yes/No.", - "enum": ["Yes", "No"] + "description": "Indicate whether a data monitoring committee has been appointed for this study. The data monitoring committee (board) is a group of independent scientists who are appointed to monitor the safety and scientific integrity of a human research intervention, and to make recommendations to the sponsor regarding the stopping of the trial for efficacy, for harms or for futility. The composition of the committee is dependent upon the scientific skills and knowledge required for monitoring the particular study.", + "enum": [ + "Yes", + "No" + ] } - } + }, + "required": [ + "humanSubjectReviewStatus" + ] }, - "DescriptionModule": { + "descriptionModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#description", "type": "object", "additionalProperties": false, "properties": { - "BriefSummary": { + "briefSummary": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets. Character limit has been kept here to ensure the summary is brief.", "type": "string", "description": "A short description of the clinical study, written in language intended for the lay public. Limit: 5000 characters", - "minLength": 1 + "minLength": 1, + "maxLength": 5000 }, - "DetailedDescription": { + "detailedDescription": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "string", - "description": "Extended description of the study, including more technical information (as compared to the Brief Summary), if desired. Do not include the entire protocol; do not duplicate information recorded in other data elements, such as Eligibility Criteria or outcome measures.For Patient Registries: Also describe the applicable registry procedures and other quality factors (for example, third party certification, on-site audit). In particular, summarize any procedures implemented as part of the patient registry, including, but not limited to the following: Quality assurance plan that addresses data validation and registry procedures, including any plans for site monitoring and auditing. Data checks to compare data entered into the registry against predefined rules for range or consistency with other data fields in the registry. Source data verification to assess the accuracy, completeness, or representativeness of registry data by comparing the data to external data sources (for example, medical records, paper or electronic case report forms, or interactive voice response systems). Data dictionary that contains detailed descriptions of each variable used by the registry, including the source of the variable, coding information if used (for example, World Health Organization Drug Dictionary, MedDRA), and normal ranges if relevant. Standard Operating Procedures to address registry operations and analysis activities, such as patient recruitment, data collection, data management, data analysis, reporting for adverse events, and change management. Sample size assessment to specify the number of participants or participant years necessary to demonstrate an effect. Plan for missing data to address situations where variables are reported as missing, unavailable, non-reported, uninterpretable, or considered missing because of data inconsistency or out-of-range results. Statistical analysis plan describing the analytical principles and statistical techniques to be employed in order to address the primary and secondary objectives, as specified in the study protocol or plan.", + "description": "Extended description of the study, including more technical information (as compared to the Brief Summary), if desired. Do not include the entire protocol; do not duplicate information recorded in other data elements, such as Eligibility Criteria or outcome measures.", "minLength": 1 } }, - "required": ["BriefSummary"] + "required": [ + "briefSummary" + ] }, - "ConditionsModule": { + "conditionsModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#Conditions", "type": "object", "additionalProperties": false, "properties": { - "ConditionList": { + "conditionList": { + "$comment": "Besides 'conditionName' all keys have been added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely map condition names to controlled vocabulary and make schema more FAIR. Descriptions and examples are based on the dataset_description schema but modified to suit here.", "type": "array", - "description": "The name(s) of the disease(s) or condition(s) studied in the clinical study, or the focus of the clinical study. Use, if available, appropriate descriptors from NLM's Medical Subject Headings (MeSH)-controlled vocabulary thesaurus or terms from another vocabulary, such as the Systematized Nomenclature of Medicine—Clinical Terms (SNOMED CT), that has been mapped to MeSH within the Unified Medical Language System (UMLS) Metathesaurus.", + "description": "The name(s) of the disease(s) or condition(s) studied in the clinical study, or the focus of the clinical study. Use, if available, appropriate descriptors from NLM's Medical Subject Headings (MeSH)-controlled vocabulary thesaurus or terms from another vocabulary, such as the Systematized Nomenclature of Medicine\u2014Clinical Terms (SNOMED CT), that has been mapped to MeSH within the Unified Medical Language System (UMLS) Metathesaurus.", "items": { - "type": "string", - "minLength": 1 + "type": "object", + "additionalProperties": false, + "properties": { + "conditionName": { + "type": "string", + "description": "Name of the condition", + "minLength": 1, + "examples": [ + "Diabetes mellitus" + ] + }, + "conditionIdentifier": { + "type": "object", + "additionalProperties": false, + "properties": { + "conditionClassificationCode": { + "type": "string", + "minLength": 1, + "description": "The classification code used for the condition name in the scheme", + "examples": [ + "45636-8" + ] + }, + "conditionScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the scheme or classification code or authority if one is used (e.g., name of ontology) for the condition name", + "examples": [ + "Logical Observation Identifier Names and Codes (LOINC)" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the condition identifier scheme", + "examples": [ + "https://loinc.org/" + ] + }, + "conditionURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the condition name in the scheme", + "examples": [ + "https://loinc.org/45636-8" + ] + } + }, + "required": [ + "conditionClassificationCode", + "conditionScheme" + ] + } + }, + "required": [ + "conditionName" + ] }, "minItems": 1, "uniqueItems": true }, - "KeywordList": { + "keywordList": { "type": "array", - "description": "Words or phrases that best describe the study. Keywords help users find studies in the database. Use NLM's Medical Subject Heading (MeSH)-controlled vocabulary terms where appropriate. Be as specific and precise as possible. Avoid acronyms and abbreviations.", + "description": "Words or phrases that best describe the study. Use NLM's Medical Subject Heading (MeSH)-controlled vocabulary terms or terms from another vocabulary where appropriate. Be as specific and precise as possible. Avoid acronyms and abbreviations.", "items": { - "type": "string", - "minLength": 1 + "type": "object", + "additionalProperties": false, + "properties": { + "keywordValue": { + "type": "string", + "description": "Keyword or phrase", + "minLength": 1, + "examples": [ + "Artificial intelligence" + ] + }, + "keywordIdentifier": { + "$comment": "Added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely map condition keywords to controlled vocabulary and make schema more FAIR. Descriptions and examples are based on the dataset_description schema but modified to suit here. Description has been modified to allow terms from another vocabulary than MeSH", + "type": "object", + "additionalProperties": false, + "properties": { + "keywordClassificationCode": { + "type": "string", + "minLength": 1, + "description": "The classification code used for the keyword in the scheme", + "examples": [ + "D001185" + ] + }, + "keywordScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the scheme or classification code or authority if one is used (e.g., name of ontology) for the keyword", + "examples": [ + "Medical Subject Headings (MeSH)" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the keyword identifier scheme", + "examples": [ + "https://meshb.nlm.nih.gov/" + ] + }, + "keywordURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the keyword in the scheme", + "examples": [ + "https://meshb.nlm.nih.gov/record/ui?ui=D001185" + ] + } + }, + "required": [ + "keywordClassificationCode", + "keywordScheme" + ] + } + }, + "required": [ + "keywordValue" + ] }, "minItems": 1, "uniqueItems": true } }, - "required": ["ConditionList"] + "required": [ + "conditionList" + ] }, - "DesignModule": { + "designModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#StudyDesign", "type": "object", - "required": ["StudyType"], + "required": [ + "studyType" + ], "properties": { - "StudyType": { + "studyType": { + "$comment": "Maps to https://prsinfo.clinicaltrials.gov/definitions.html#StudyType", "type": "string", - "description": "The type of study being registered.", + "description": "The nature of the investigation", "oneOf": [ { "const": "Interventional", @@ -271,12 +717,9 @@ "description": "Studies in human beings in which biomedical and/or health outcomes are assessed in pre-defined groups of individuals. Participants in the study may receive diagnostic, therapeutic, or other interventions, but the investigator does not assign specific interventions to the study participants. This includes when participants receive interventions as part of routine medical care, and a researcher studies the effect of the intervention." }, { - "const": "Observational Patient Registry", - "description": "An observational study that is also considered to be a Patient Registry. Note: The Agency for Healthcare Research and Quality (AHRQ) defines a Patient Registry as including an organized system that uses observational methods to collect uniform data (clinical and other) prospectively for a population defined by a particular disorder/disease, condition (including susceptibility to a disorder), or exposure (including products, healthcare services, and/or procedures) and that serves a predetermined scientific, clinical, or policy purpose. Patient registries may be single purpose or on-going data collection programs that address one or more questions." - }, - { + "$comment": "Description changed to suit dataset", "const": "Expanded Access", - "description": "An investigational drug product (including biological product) available through expanded access for patients who do not qualify for enrollment in a clinical trial. Expanded Access includes all expanded access types under section 561 of the Federal Food, Drug, and Cosmetic Act: (1) for individual patients, including emergency use; (2) for intermediate-size patient populations; and (3) under a treatment IND or treatment protocol. (For more information on data requirements for this Study Type, see Expanded Access Data Element $defs)." + "description": "An investigational drug product (including biological product) available through expanded access for patients who do not qualify for enrollment in a clinical trial. Expanded Access includes all expanded access types under section 561 of the Federal Food, Drug, and Cosmetic Act: (1) for individual patients, including emergency use; (2) for intermediate-size patient populations; and (3) under a treatment IND or treatment protocol." } ] } @@ -285,19 +728,19 @@ { "if": { "properties": { - "StudyType": { + "studyType": { "const": "Interventional" } } }, "then": { "properties": { - "DesignInfo": { + "designInfo": { "type": "object", "description": "A description of the manner in which the clinical trial will be conducted.", "additionalProperties": false, "properties": { - "DesignAllocation": { + "designAllocation": { "type": "string", "description": "The process by which participants are assigned to a clinical study. Types of allocation include randomized and nonrandomized. Interventions in a nonrandomized study are not assigned randomly.", "oneOf": [ @@ -315,7 +758,7 @@ } ] }, - "DesignInterventionModel": { + "designInterventionModel": { "type": "string", "description": "The strategy for assigning interventions to participants.", "oneOf": [ @@ -353,12 +796,12 @@ } ] }, - "DesignInterventionModelDescription": { + "designInterventionModelDescription": { "type": "string", "description": "Provide details about the Interventional Study Model", "minLength": 1 }, - "DesignPrimaryPurpose": { + "designPrimaryPurpose": { "type": "string", "description": "The main objective of the intervention(s) being evaluated by the clinical trial.", "oneOf": [ @@ -384,12 +827,12 @@ } ] }, - "DesignMaskingInfo": { + "designMaskingInfo": { "type": "object", - "description": " The party or parties involved in the clinical trial who are prevented from having knowledge of the interventions assigned to individual participants.", + "description": "The party or parties involved in the clinical trial who are prevented from having knowledge of the interventions assigned to individual participants.", "additionalProperties": false, "properties": { - "DesignMasking": { + "designMasking": { "type": "string", "oneOf": [ { @@ -417,12 +860,7 @@ } ] }, - "DesignMaskingDescription": { - "type": "string", - "description": "Provide information about other parties who may be masked in the clinical trial, if any.", - "minLength": 1 - }, - "DesignWhoMaskedList": { + "designWhoMaskedList": { "type": "array", "items": { "type": "string", @@ -444,19 +882,27 @@ }, "minItems": 1, "uniqueItems": true + }, + "designMaskingDescription": { + "type": "string", + "description": "Provide information about other parties who may be masked in the clinical trial, if any.", + "minLength": 1 } }, - "required": ["DesignMasking", "DesignWhoMaskedList"] + "required": [ + "designMasking", + "designWhoMaskedList" + ] } }, "required": [ - "DesignAllocation", - "DesignInterventionModel", - "DesignPrimaryPurpose", - "DesignMaskingInfo" + "designAllocation", + "designInterventionModel", + "designPrimaryPurpose", + "designMaskingInfo" ] }, - "PhaseList": { + "phaseList": { "type": "array", "description": "For a clinical trial of a drug product (including a biological product), the numerical phase of such clinical trial, consistent with terminology in 21 CFR 312.21 and in 21 CFR 312.85 for phase 4 studies. Select only one.", "items": { @@ -500,10 +946,11 @@ "maxItems": 1, "uniqueItems": true }, - "EnrollmentInfo": { - "$ref": "#/$defs/enrollmentInfo" + "enrollmentInfo": { + "$ref": "#/definitions/enrollmentInfo" }, - "NumberArms": { + "numberArms": { + "$comment": "This key is not in the ClinicalTrials.gov JSON study record but it has been added here to match the corresponding the Data Elements", "type": "string", "pattern": "^[0-9]+$", "minLength": 1, @@ -511,29 +958,39 @@ } }, "required": [ - "DesignInfo", - "PhaseList", - "EnrollmentInfo", - "NumberArms" + "designInfo", + "phaseList", + "enrollmentInfo", + "numberArms" ] } }, { "if": { "properties": { - "StudyType": { + "studyType": { "const": "Observational" } } }, "then": { "properties": { - "DesignInfo": { + "isPatientRegistry": { + "$comment": "This key is not in the ClinicalTrials.gov JSON study record but it has been added here to specify if an observational study is a Patient Registry.", + "type": "string", + "description": "Indicate if the observational study is a Patient Registry, i.e., an observational study that is also considered to be a Patient Registry. Note: The Agency for Healthcare Research and Quality (AHRQ) defines a Patient Registry as including an organized system that uses observational methods to collect uniform data (clinical and other) prospectively for a population defined by a particular disorder/disease, condition (including susceptibility to a disorder), or exposure (including products, healthcare services, and/or procedures) and that serves a predetermined scientific, clinical, or policy purpose. Patient registries may be single purpose or on-going data collection programs that address one or more questions.", + "enum": [ + "Yes", + "No" + ] + }, + "designInfo": { + "$comment": "Description has been added here since none was provided in the ClinicalTrials.gov Data Elements", "type": "object", "description": "A description of the manner in which the observational study will be conducted", "additionalProperties": false, "properties": { - "DesignObservationalModelList": { + "designObservationalModelList": { "type": "array", "description": "Primary strategy for participant identification and follow-up.", "items": { @@ -565,14 +1022,14 @@ }, { "const": "Other", - "description": "Explain in Detailed Description.." + "description": "Explain in Detailed Description." } ] }, "minItems": 1, "uniqueItems": true }, - "DesignTimePerspectiveList": { + "designTimePerspectiveList": { "type": "array", "description": "Temporal relationship of the observation period to the time of participant enrollment.", "items": { @@ -601,15 +1058,16 @@ } }, "required": [ - "DesignObservationalModelList", - "DesignTimePerspectiveList" + "designObservationalModelList", + "designTimePerspectiveList" ] }, - "BioSpec": { + "bioSpec": { + "$comment": "Made mandatory here", "type": "object", "additionalProperties": false, "properties": { - "BioSpecRetention": { + "bioSpecRetention": { "type": "string", "description": "Indicate whether samples of material from research participants are retained in a biorepository.", "oneOf": [ @@ -627,58 +1085,69 @@ } ] }, - "BioSpecDescription": { + "bioSpecDescription": { "type": "string", "description": "Specify all types of biospecimens to be retained (e.g., whole blood, serum, white cells, urine, tissue).", "minLength": 1 } }, - "required": ["BioSpecRetention"] + "required": [ + "bioSpecRetention", + "bioSpecDescription" + ] }, - "EnrollmentInfo": { - "$ref": "#/$defs/enrollmentInfo" + "enrollmentInfo": { + "$ref": "#/definitions/enrollmentInfo" }, - "TargetDuration": { + "targetDuration": { "type": "string", "description": "For Patient Registries, the anticipated time period over which each participant is to be followed.", "minLength": 1, - "examples": ["3 Years", "5 Days", "10 Weeks"] - }, - "NumberGroupsCohorts": { - "type": "string", - "pattern": "^[0-9]+$", - "minLength": 1, - "description": "Number of study groups/cohorts. Enter `1` for a single-group study. Many observational studies have one group/cohort; case control studies typically have two. The minimum value is '1'." + "pattern": "^[0-9]+(\\.[0-9]+)?\\s*(Years|Months|Weeks|Days|Hours)?$" } }, "required": [ - "DesignInfo", - "EnrollmentInfo", - "TargetDuration", - "NumberGroupsCohorts" - ] + "isPatientRegistry", + "designInfo", + "bioSpec", + "enrollmentInfo" + ], + "if": { + "properties": { + "isPatientRegistry": { + "const": "Yes" + } + } + }, + "then": { + "required": [ + "targetDuration" + ] + } } } ] }, - "ArmsInterventionsModule": { + "armsInterventionsModule": { + "$comment": "https://prsinfo.clinicaltrials.gov/definitions.html#ArmsGroupsInterventions", "type": "object", "additionalProperties": false, "properties": { - "ArmGroupList": { + "armGroupList": { "type": "array", "items": { "type": "object", "description": "If the study is interventional: A description of each arm of the clinical trial that indicates its role in the clinical trial; provides an informative title; and, if necessary, additional descriptive information (including which interventions are administered in each arm) to differentiate each arm from other arms in the clinical trial. || If the study is observational: Specify the predefined participant groups (cohorts) to be studied, corresponding to Number of Groups specified under Study Design (for single-group studies, the following data elements are optional). Do not use this section to specify strata (Detailed Description can be used for that purpose, if desired).", "additionalProperties": false, "properties": { - "ArmGroupLabel": { + "armGroupLabel": { + "description": "If the study is interventional: The short name used to identify the arm. || If the study is observational: The short name used to identify the group.", "type": "string", "minLength": 1 }, - "ArmGroupType": { + "armGroupType": { "type": "string", - "description": "required if study type is interventional", + "description": "Required only if study type is interventional", "enum": [ "Experimental", "Active Comparator", @@ -688,13 +1157,15 @@ "Other" ] }, - "ArmGroupDescription": { + "armGroupDescription": { + "$comment": "Made mandatory here since otherwise it would not be possible to understand the labels", + "description": "If the study is interventional: If needed, additional descriptive information (including which interventions are administered in each arm) to differentiate each arm from other arms in the clinical trial. || Explanation of the nature of the study group (for example, those with a condition and those without a condition; those with an exposure and those without an exposure).", "type": "string", "minLength": 1 }, - "ArmGroupInterventionList": { + "armGroupInterventionList": { "type": "array", - "description": "required if study type is interventional and there is more than one intervention", + "description": "Indicate which Interventions (from the intervention list) are in this Arm/Group (must match with interventionName)", "items": { "type": "string", "minLength": 1 @@ -703,19 +1174,23 @@ "uniqueItems": true } }, - "required": ["ArmGroupLabel"] + "required": [ + "armGroupLabel", + "armGroupDescription" + ] }, "minItems": 1, "uniqueItems": true }, - "InterventionList": { + "interventionList": { + "$comment": "'interventionArmGroupLabelList' has been removed here since it the cross-connection information between interventions and arms/groups is already captured in 'armGroupInterventionList'", "type": "array", "description": "Specify the intervention(s) associated with each arm or group; at least one intervention must be specified for interventional studies. For observational studies, specify the intervention(s)/exposure(s) of interest, if any. If the same intervention is associated with more than one arm or group, provide the information once and use the Arm or Group/Intervention Cross-Reference to associate it with more than one arm or group.", "items": { "type": "object", "additionalProperties": false, "properties": { - "InterventionType": { + "interventionType": { "type": "string", "description": "For each intervention studied in the clinical study, the general type of intervention. Select one.", "oneOf": [ @@ -765,27 +1240,17 @@ } ] }, - "InterventionName": { + "interventionName": { "type": "string", "description": "A brief descriptive name used to refer to the intervention(s) studied in each arm of the clinical study. A non-proprietary name of the intervention must be used, if available. If a non-proprietary name is not available, a brief descriptive name or identifier must be used.", "minLength": 1 }, - "InterventionDescription": { + "interventionDescription": { "type": "string", "description": "Details that can be made public about the intervention, other than the Intervention Name(s) and Other Intervention Name(s), sufficient to distinguish the intervention from other, similar interventions studied in the same or another clinical study. For example, interventions involving drugs may include dosage form, dosage, frequency, and duration", "minLength": 1 }, - "InterventionArmGroupLabelList": { - "type": "array", - "description": "The name of the arm or group associated with the intervention studied in this clinical study. At least one Arm Group Label must be provided.", - "items": { - "type": "string", - "minLength": 1 - }, - "minItems": 1, - "uniqueItems": true - }, - "InterventionOtherNameList": { + "interventionOtherNameList": { "type": "array", "description": "Other current and former name(s) or alias(es), if any, different from the Intervention Name(s), that the sponsor has used publicly to identify the intervention(s), including, but not limited to, past or present names such as brand name(s), or serial numbers.", "items": { @@ -797,22 +1262,26 @@ } }, "required": [ - "InterventionType", - "InterventionName", - "InterventionArmGroupLabelList" + "interventionType", + "interventionName", + "interventionDescription" ] }, "minItems": 1, "uniqueItems": true } }, - "required": ["ArmGroupList", "InterventionList"] + "required": [ + "armGroupList", + "interventionList" + ] }, - "EligibilityModule": { + "eligibilityModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#Eligibility", "type": "object", "additionalProperties": false, "properties": { - "Gender": { + "sex": { "type": "string", "description": "The sex and, if applicable, gender of the participants eligible to participate in the clinical study. The sex of the participants eligible to participate in the clinical study. Note: 'Sex' means a person's classification as male or female based on biological distinctions.", "oneOf": [ @@ -830,45 +1299,77 @@ } ] }, - "GenderBased": { + "genderBased": { "type": "string", "description": "If applicable, indicate whether participant eligibility is based on gender. Note: 'Gender' means a person's self-representation of gender identity.", - "enum": ["Yes", "No"] + "enum": [ + "Yes", + "No" + ] }, - "GenderDescription": { + "genderDescription": { "type": "string", "description": "If eligibility is based on gender, provide descriptive information about Gender criteria." }, - "MinimumAge": { + "minimumAge": { "type": "string", "description": "The numerical value, if any, for the minimum age a potential participant must meet to be eligible for the clinical study. Include a whole number followed by units, if no limit use 'N/A' - see controlled values for units", "pattern": "^[0-9]+(\\.[0-9]+)?\\s*(Years|Months|Weeks|Days|Hours|N/A)?$", "minLength": 1 }, - "MaximumAge": { + "maximumAge": { "type": "string", "description": "The numerical value, if any, for the maximum age a potential participant must meet to be eligible for the clinical study. Include a whole number followed by units, if no limit use 'N/A' - see controlled values for units", "pattern": "^[0-9]+(\\.[0-9]+)?\\s*(Years|Months|Weeks|Days|Hours|N/A)?$", "minLength": 1 }, - "HealthyVolunteers": { + "healthyVolunteers": { + "$comment": "Made mandatory for both interventional and observational studies", "type": "string", - "description": "Indication that participants who do not have a disease or condition, or related conditions or symptoms, under study in the clinical study are permitted to participate in the clinical study. Required if the study type is Interventional.", - "enum": ["Yes", "No"] + "description": "Indication that participants who do not have a disease or condition, or related conditions or symptoms, under study in the clinical study are permitted to participate in the clinical study.", + "enum": [ + "Yes", + "No" + ] }, - "EligibilityCriteria": { - "type": "string", - "description": "A limited list of criteria for selection of participants in the clinical study, provided in terms of inclusion and exclusion criteria and suitable for assisting potential participants in identifying clinical studies of interest. Use a bulleted list for each criterion below the headers 'Inclusion Criteria' and 'Exclusion Criteria'", - "minLength": 1 + "eligibilityCriteria": { + "$comment": "This is a string in the ClinicalTrials.gov JSON study record but made an object here to better separate inclusion and exclusion criteria. Description has been modified to suit datasets.", + "type": "object", + "description": "A limited list of criteria for selection of participants in the clinical study, provided in terms of inclusion and exclusion criteria.", + "properties": { + "eligibilityCriteriaInclusion": { + "type": "array", + "items": { + "type": "string", + "description": "An inclusion criterion", + "minLength": 1 + }, + "minItems": 1, + "uniqueItems": true + }, + "eligibilityCriteriaExclusion": { + "items": { + "type": "string", + "description": "An exclusion criterion", + "minLength": 1 + }, + "minItems": 1, + "uniqueItems": true + } + }, + "required": [ + "eligibilityCriteriaInclusion", + "eligibilityCriteriaExclusion" + ] }, - "StudyPopulation": { + "studyPopulation": { "type": "string", - "description": "A description of the population from which the groups or cohorts will be selected (for example, primary care clinic, community sample, residents of a certain town). Required for observational studies.", + "description": "A description of the population from which the groups or cohorts will be selected (for example, primary care clinic, community sample, residents of a certain town). Required for observational studies only.", "minLength": 1 }, - "SamplingMethod": { + "samplingMethod": { "type": "string", - "description": "The method used to select participants to be studied. Required for observational studies.", + "description": "The method used to select participants to be studied. Required for observational studies only.", "oneOf": [ { "const": "Probability Sample", @@ -882,76 +1383,267 @@ } }, "required": [ - "Gender", - "GenderBased", - "MinimumAge", - "MaximumAge", - "EligibilityCriteria" + "sex", + "genderBased", + "minimumAge", + "maximumAge", + "healthyVolunteers", + "eligibilityCriteria" ] }, - "ContactsLocationsModule": { + "contactsLocationsModule": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#Locations", "type": "object", "additionalProperties": false, "properties": { - "CentralContactList": { + "centralContactList": { + "$comment": "Description is based on the ClinicalTrials.gov Data Elements but modified to suit datasets", "type": "array", - "description": "The name or title, toll-free telephone number, and email address of a person to whom questions concerning enrollment at any location of the study can be addressed.", + "description": "The contact of a person to whom questions about the study can be addressed.", "items": { "type": "object", "additionalProperties": false, "properties": { - "CentralContactName": { + "centralContactFirstName": { + "$comment": "Added in lieu of centralContactName", "type": "string", "minLength": 1 }, - "CentralContactAffiliation": { + "centralContactLastName": { + "$comment": "Added in lieu of centralContactName", "type": "string", - "description": "If none, specify Unaffiliated.", "minLength": 1 }, - "CentralContactPhone": { + "centralContactDegree": { + "$comment": "Added here", + "type": "string", + "minLength": 1 + }, + "centralContactIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify the central contact and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "array", + "description": "Uniquely identifies a central contract, according to various schemes.", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "centralContactIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies an central contact.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427" + ] + }, + "centralContactIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the central contact identifier scheme.", + "examples": [ + "ORCID" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the central contact identifier scheme.", + "examples": [ + "https://orcid.org" + ] + } + }, + "required": [ + "centralContactIdentifierValue", + "centralContactIdentifierScheme" + ] + }, + "uniqueItems": true + }, + "centralContactAffiliation": { + "type": "object", + "additionalProperties": false, + "properties": { + "centralContactAffiliationName": { + "type": "string", + "description": "The name of the affiliation of the central contact", + "minLength": 1 + }, + "centralContactAffiliationIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify central contact affiliation and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "centralContactAffiliationIdentifierValue": { + "type": "string", + "description": "Uniquely identifies central contact affiliation, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "centralContactAffiliationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "centralContactAffiliationIdentifierValue", + "centralContactAffiliationIdentifierScheme" + ] + } + }, + "required": [ + "centralContactAffiliationName" + ] + }, + "centralContactPhone": { "type": "string", "description": "Toll-free phone number of the Central Contact Person. Use the format 800-555-5555 within the United States and Canada. If outside the United States and Canada, provide the full phone number, including the country code. 30 characters", "minLength": 1, "maxLength": 30 }, - "CentralContactPhoneExt": { + "centralContactPhoneExt": { "type": "string", "description": "phone extension, if needed.", "minLength": 1 }, - "CentralContactEMail": { + "centralContactEMail": { "type": "string", "description": "Email address of the Central Contact Person", "minLength": 1 } }, "required": [ - "CentralContactName", - "CentralContactAffiliation", - "CentralContactPhone", - "CentralContactEMail" + "centralContactFirstName", + "centralContactLastName", + "centralContactAffiliation", + "centralContactEMail" ] }, "minItems": 1, "uniqueItems": true }, - "OverallOfficialList": { + "overallOfficialList": { "type": "array", + "description": "Person(s) responsible for the overall scientific leadership of the protocol, including study principal investigator.", "items": { "type": "object", "additionalProperties": false, "properties": { - "OverallOfficialName": { + "overallOfficialFirstName": { "type": "string", "minLength": 1 }, - "OverallOfficialAffiliation": { + "overallOfficialLastName": { "type": "string", - "description": "Full name of the official's organization. If none, specify Unaffiliated.", "minLength": 1 }, - "OverallOfficialRole": { + "overallOfficialDegree": { + "type": "string", + "minLength": 1 + }, + "overallOfficialIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify the official and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "array", + "description": "Uniquely identifies an official, according to various schemes.", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "overallOfficialIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies an official.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427" + ] + }, + "overallOfficialIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the official identifier scheme.", + "examples": [ + "ORCID" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the official identifier scheme.", + "examples": [ + "https://orcid.org" + ] + } + }, + "required": [ + "overallOfficialIdentifierValue", + "overallOfficialIdentifierScheme" + ] + }, + "uniqueItems": true + }, + "overallOfficialAffiliation": { + "type": "object", + "additionalProperties": false, + "properties": { + "overallOfficialAffiliationName": { + "type": "string", + "description": "Full name of the official's organization.", + "minLength": 1 + }, + "overallOfficialAffiliationIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify official affiliation and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "overallOfficialAffiliationIdentifierValue": { + "type": "string", + "description": "Uniquely identifies official affiliation, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "overallOfficialAffiliationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "overallOfficialAffiliationIdentifierValue", + "overallOfficialAffiliationIdentifierScheme" + ] + } + }, + "required": [ + "overallOfficialAffiliationName" + ] + }, + "overallOfficialRole": { "type": "string", "description": "Position or function of the official.", "enum": [ @@ -962,50 +1654,86 @@ } }, "required": [ - "OverallOfficialName", - "OverallOfficialAffiliation", - "OverallOfficialRole" + "overallOfficialFirstName", + "overallOfficialLastName", + "overallOfficialAffiliation", + "overallOfficialRole" ] }, "minItems": 1, "uniqueItems": true }, - "LocationList": { + "locationList": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { - "LocationFacility": { + "locationFacility": { "type": "string", "description": "Full name of the organization where the clinical study is being conducted.", "minLength": 1 }, - "LocationStatus": { - "$ref": "#/$defs/statusOptions", + "locationStatus": { + "$ref": "#/definitions/statusOptions", "description": "The recruitment status of each participating facility in a clinical study." }, - "LocationCity": { + "locationCity": { "type": "string", "description": "City of the location of the clinical study.", "minLength": 1 }, - "LocationState": { + "locationState": { "type": "string", "description": "State or province of the location of the clinical study. Required for U.S. locations (including territories of the United States)", "minLength": 1 }, - "LocationZip": { + "locationZip": { "type": "string", "description": "Zip or postal code of the location of the clinical study. Required for U.S. locations (including territories of the United States)", "minLength": 1 }, - "LocationCountry": { + "locationCountry": { "type": "string", "description": "Country of the location of the clinical study.", "minLength": 1 }, - "LocationContactList": { + "locationIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify location and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "object", + "additionalProperties": false, + "properties": { + "locationIdentifierValue": { + "type": "string", + "description": "Uniquely identifies location, according to various schemes.", + "minLength": 1, + "examples": [ + "https://ror.org/04aj4c18" + ] + }, + "locationIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the identifier scheme.", + "examples": [ + "ROR" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the name identifier scheme.", + "examples": [ + "https://ror.org" + ] + } + }, + "required": [ + "locationIdentifierValue", + "locationIdentifierScheme" + ] + }, + "locationContactList": { "type": "array", "description": "Required if Central Contact is not provided", "items": { @@ -1013,36 +1741,84 @@ "description": "For each facility participating in a clinical study, including the name or title, telephone number, and email address of a person to whom questions concerning the study and enrollment at that site can be addressed. Include the following information.", "additionalProperties": false, "properties": { - "LocationContactName": { + "locationContactFirstName": { "type": "string", "minLength": 1 }, - "LocationContactRole": { + "locationContactLastName": { + "type": "string", + "minLength": 1 + }, + "locationContactIdentifier": { + "$comment": "Key added based on the dataset_description.json schema https://schema.aireadi.org/files/dataset_description.json (which is based on DataCite) to uniquely identify the location contact and make schema more FAIR. Description and examples are based on the dataset_description schema but modified to suit here.", + "type": "array", + "description": "Uniquely identifies a location contract, according to various schemes.", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "locationContactIdentifierValue": { + "type": "string", + "minLength": 1, + "description": "Uniquely identifies a location contact.", + "examples": [ + "https://orcid.org/0000-0001-5727-2427" + ] + }, + "locationContactIdentifierScheme": { + "type": "string", + "minLength": 1, + "description": "The name of the location contact identifier scheme.", + "examples": [ + "ORCID" + ] + }, + "schemeURI": { + "type": "string", + "minLength": 1, + "description": "The URI of the location contact identifier scheme.", + "examples": [ + "https://orcid.org" + ] + } + }, + "required": [ + "centralContactIdentifierValue", + "locationContactIdentifierScheme" + ] + }, + "uniqueItems": true + }, + "locationContactRole": { "type": "string", "description": "Position or function of the contact person.", - "enum": ["Principal Investigator", "Sub-Investigator"] + "enum": [ + "Principal Investigator", + "Sub-Investigator" + ] }, - "LocationContactPhone": { + "locationContactPhone": { "type": "string", "description": "Office phone of the Facility Contact.", "minLength": 1 }, - "LocationContactPhoneExt": { + "locationContactPhoneExt": { "type": "string", "description": "phone extension, if needed.", "minLength": 1 }, - "LocationContactEMail": { + "locationContactEMail": { "type": "string", "description": "Electronic mail address of the facility contact person", "minLength": 1 } }, "required": [ - "LocationContactName", - "LocationContactRole", - "LocationContactPhone", - "LocationContactEMail" + "locationContactFirstName", + "locationContactLastName", + "locationContactRole", + "locationContactPhone", + "locationContactEMail" ] }, "minItems": 1, @@ -1050,234 +1826,67 @@ } }, "required": [ - "LocationFacility", - "LocationStatus", - "LocationCity", - "LocationCountry" - ] - }, - "minItems": 1, - "uniqueItems": true - } - }, - "required": ["LocationList"] - }, - "IPDSharingStatementModule": { - "type": "object", - "additionalProperties": false, - "required": ["IPDSharing"], - "properties": { - "IPDSharing": { - "type": "string", - "description": "Indicate whether there is a plan to make individual participant data (IPD) collected in this study, including data dictionaries, available to other researchers (typically after the end of the study).", - "oneOf": [ - { - "const": "Yes", - "description": "There is a plan to make IPD and related data dictionaries available." - }, - { - "const": "No", - "description": "There is no plan to make IPD available." - }, - { - "const": "Undecided", - "description": "It is not yet known if there will be a plan to make IPD available." - } - ] - }, - "IPDSharingDescription": { - "type": "string", - "description": "If Plan to Share IPD is 'Yes' briefly describe what specific individual participant data sets are to be shared (for example, all collected IPD, all IPD that underlie results in a publication). If the Plan to Share IPD is 'No' or 'Undecided' an explanation may be provided for why IPD will not be shared or why it is not yet decided.", - "minLength": 1 - }, - "IPDSharingInfoTypeList": { - "type": "array", - "description": "The type(s) of supporting information that will be shared, in addition to the individual participant data set and data dictionaries for the IPD itself.", - "items": { - "type": "string", - "enum": [ - "Study Protocol", - "Statistical Analysis Plan (SAP)", - "Informed Consent Form (ICF)", - "Clinical Study Report (CSR)", - "Analytic Code" + "locationFacility", + "locationStatus", + "locationCity", + "locationCountry" ] }, "minItems": 1, "uniqueItems": true - }, - "IPDSharingTimeFrame": { - "type": "string", - "description": "A description of when the IPD and any additional supporting information will become available and for how long, including the start and end dates or period of availability. This may be provided as an absolute date (for example, starting in January 2025) or as a date relative to the time when summary data are published or otherwise made available (for example, starting 6 months after publication).", - "minLength": 1 - }, - "IPDSharingAccessCriteria": { - "type": "string", - "description": "Describe by what access criteria IPD and any additional supporting information will be shared, including with whom, for what types of analyses, and by what mechanism. Information about who will review requests and criteria for reviewing requests may also be provided.", - "minLength": 1 - }, - "IPDSharingURL": { - "type": "string", - "description": "The web address, if any, used to find additional information about the plan to share IPD.", - "format": "uri", - "minLength": 1 - } - }, - "if": { - "properties": { - "IPDSharing": { - "const": "Yes" - } } }, - "then": { - "required": [ - "IPDSharingDescription", - "IPDSharingInfoTypeList", - "IPDSharingTimeFrame", - "IPDSharingAccessCriteria", - "IPDSharingURL" - ] - } - }, - "ReferencesModule": { - "type": "object", - "additionalProperties": false, - "properties": { - "ReferenceList": { - "type": "array", - "description": "Citations to publications related to the study: background and/or results. Provide either the PubMed Unique Identifier (PMID) or the DOI of an article or enter the full bibliographic citation.", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "ReferenceID": { - "type": "string", - "description": "The PubMed Unique Identifier (PMID) or the DOI of an article.", - "minLength": 1 - }, - "ReferenceType": { - "type": "string", - "description": "Indicate if the reference provided reports on results from this clinical study.", - "enum": ["Yes", "No"] - }, - "ReferenceCitation": { - "type": "string", - "description": "A bibliographic reference in NLM's MEDLINE format.", - "minLength": 1 - } - }, - "required": ["ReferenceCitation"] - }, - "minItems": 1, - "uniqueItems": true - }, - "SeeAlsoLinkList": { - "type": "array", - "description": "A website directly relevant to the protocol may be entered, if desired. Do not include sites that aim to advertise or sell commercial products or services. Links to educational, research, government, and other non-profit web pages are acceptable. All submitted links are subject to review by ClinicalTrials.gov.", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "SeeAlsoLinkLabel": { - "type": "string", - "description": "Title or brief description of the linked page.", - "minLength": 1 - }, - "SeeAlsoLinkURL": { - "type": "string", - "description": "Complete URL, including http:// or https://", - "format": "uri", - "minLength": 1 - } - }, - "required": ["SeeAlsoLinkURL"] - }, - "minItems": 1, - "uniqueItems": true - }, - "AvailIPDList": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "AvailIPDId": { - "type": "string", - "description": "The unique identifier used by a data repository for the data set or supporting information.", - "minLength": 1 - }, - "AvailIPDType": { - "type": "string", - "description": "The type of data set or supporting information.", - "enum": [ - "Individual Participant Data Set", - "Study Protocol", - "Statistical Analysis Plan", - "Informed Consent Form", - "Clinical Study Report", - "Analytic Code", - "Other" - ] - }, - "AvailIPDURL": { - "type": "string", - "description": "The web address, if any, used to find additional information about the availability of the data set or supporting information.", - "format": "uri", - "minLength": 1 - }, - "AvailIPDComment": { - "type": "string", - "description": "Additional information including the name of the data repository or other location where the data set or supporting information is available. Provide any additional explanations about the data set or supporting information and instructions for obtaining access, particularly if a URL is not provided.", - "minLength": 1 - } - }, - "required": ["AvailIPDId", "AvailIPDType", "AvailIPDURL"] - }, - "minItems": 1, - "uniqueItems": true - } - } + "required": [ + "locationList" + ] } }, "required": [ - "IdentificationModule", - "StatusModule", - "SponsorCollaboratorsModule", - "DescriptionModule", - "DesignModule", - "ArmsInterventionsModule", - "ConditionsModule", - "EligibilityModule", - "ContactsLocationsModule" + "schema", + "identificationModule", + "statusModule", + "sponsorCollaboratorsModule", + "descriptionModule", + "designModule", + "armsInterventionsModule", + "conditionsModule", + "eligibilityModule", + "contactsLocationsModule" ], - "$defs": { + "definitions": { "studyIdType": { + "$comment": "Maps to controlled list in https://prsinfo.clinicaltrials.gov/definitions.html#SecondaryIdType. 'ClinicalTrials.gov' option has been introduced here. Descriptions have been modified to suit datasets. Could be extended in the future to include other identifier types used for clinical research studies", "type": "string", "oneOf": [ { - "const": "NIH Grant Number", + "$comment": "Description based on https://classic.clinicaltrials.gov/ct2/about-studies/glossary#:~:text=A%20unique%20identification%20code%20given,called%20the%20ClinicalTrials.gov%20identifier.", + "const": "ClinicalTrials.gov", + "description": "A unique identification code given to each clinical study record registered on ClinicalTrials.gov. The format is 'NCT' followed by an 8-digit number (for example, NCT00000419)." + }, + { + "const": "U.S. National Institutes of Health (NIH) Grant/Contract Award Number", "description": "In the ID field, include activity code, institute code, and 6-digit serial number. Other components of the full award number (type code, support year, and suffix) are optional." }, { "const": "Other Grant/Funding Number", - "description": "Identifier assigned by a funding organization other than the U.S. NIH; also required to enter the name of the funding organization." + "description": "Identifier assigned by a funding organization other than the U.S. NIH; also required to enter the name of the funding organization in the ID domain field." }, { "const": "Registry Identifier", - "description": "Number assigned by a clinical trial registry (for example, a registry that is part of the World Health Organization [WHO] Registry Network); also required to enter the name of the clinical trial registry.." + "description": "Number assigned by a clinical trial registry (for example, a registry that is part of the World Health Organization [WHO] Registry Network); also required to enter the name of the clinical trial registry in the ID domain field." }, { "const": "EudraCT Number", - "description": "Identifier assigned by the European Medicines Agency Clinical Trials Database (EudraCT).." + "description": "Identifier assigned by the European Medicines Agency Clinical Trials Database (EudraCT)." }, { "const": "Other Identifier", - "description": "Also required to enter a brief description of the identifier (for example, the name of the organization that issued the identifier).." + "description": "Also required to enter a brief description of the identifier (for example, the name of the organization that issued the identifier) in the ID domain field." } ] }, "statusOptions": { + "$comment": "Maps to controlled list in https://prsinfo.clinicaltrials.gov/definitions.html#OverallStatus", "type": "string", "oneOf": [ { @@ -1314,22 +1923,59 @@ } ] }, + "humanSubjectReviewStatus": { + "$comment": "Maps to controlled list in https://prsinfo.clinicaltrials.gov/definitions.html#HumanSubject", + "type": "string", + "oneOf": [ + { + "const": "Request not yet submitted", + "description": "Review board approval is required but has not yet been requested" + }, + { + "const": "Submitted, pending", + "description": "Review board approval has been requested but not yet granted" + }, + { + "const": "Submitted, approved", + "description": "Review board approval has been requested and obtained" + }, + { + "const": "Exempt", + "description": "An exemption in accord with applicable law and regulation has been granted" + }, + { + "const": "Submitted, denied", + "description": "Review board has denied the approval request" + }, + { + "const": "Submission not required", + "description": "Review board approval is not required because the study is not subject to laws, regulations, or applicable institutional policies requiring human subjects review" + } + ] + }, "enrollmentInfo": { + "$comment": "Maps to Data Elements in https://prsinfo.clinicaltrials.gov/definitions.html#IntEnrollment", "type": "object", "additionalProperties": false, "properties": { - "EnrollmentCount": { + "enrollmentCount": { "type": "string", "pattern": "^[0-9]+$", "minLength": 1, "description": "The estimated total number of participants to be enrolled (target number) or the actual total number of participants that are enrolled in the clinical study. Note: 'Enrolled' means a participant's, or their legally authorized representative's, agreement to participate in a clinical study following completion of the informed consent process. Potential participants who are screened for the purpose of determining eligibility for a study, but do not participate in the study, are not considered enrolled, unless otherwise specified by the protocol. The min value is '1'." }, - "EnrollmentType": { + "enrollmentType": { "type": "string", - "enum": ["Anticipated", "Actual"] + "enum": [ + "Anticipated", + "Actual" + ] } }, - "required": ["EnrollmentCount", "EnrollmentType"] + "required": [ + "enrollmentCount", + "enrollmentType" + ] } } -} +} \ No newline at end of file diff --git a/pyfairdatatools/standards.py b/pyfairdatatools/standards.py new file mode 100644 index 0000000..ada4b09 --- /dev/null +++ b/pyfairdatatools/standards.py @@ -0,0 +1,50 @@ +from abc import abstractmethod + + +class DataDomain: + """ + Abstract base class for defining data domain implementations. + + This class defines an abstract interface for data domain implementations. Subclasses + are expected to provide concrete implementations for the 'convert' and 'metadata' methods. + + Methods: + convert(infile, outfile, **kwargs): Abstract method to convert data from an input file to an output file. + metadata(files, outfile, **kwargs): Abstract method to extract metadata from files and save it. + """ + + def __init__(self): + """ + Initialize the base class for data domain implementations. + """ + print("in standards init") + + @abstractmethod + def convert(self, infile, outfile, **kwargs): + """ + Convert data from an input file to an output file. + + This method is an abstract method that must be overridden in concrete subclasses. + + Args: + infile (str): Path to the input file. + outfile (str): Path to the output file. + **kwargs: Additional keyword arguments specific to the implementation. + + """ + pass + + @abstractmethod + def metadata(self, files, outfile, **kwargs): + """ + Extract metadata from files and save it. + + This method is an abstract method that must be overridden in concrete subclasses. + + Args: + files (list): List of input file paths. + outfile (str): Path to the output file for saving metadata. + **kwargs: Additional keyword arguments specific to the implementation. + + """ + pass diff --git a/pyfairdatatools/utils.py b/pyfairdatatools/utils.py index f46cb11..0720736 100644 --- a/pyfairdatatools/utils.py +++ b/pyfairdatatools/utils.py @@ -1,8 +1,10 @@ import os import requests +import random import validators from validators import ValidationFailure +import string def feet_to_meters(feet): @@ -17,6 +19,7 @@ def feet_to_meters(feet): def requestJSON(url): + """Make a GET request to a URL and return the JSON response.""" try: response = requests.request("GET", url, headers={}, data={}, timeout=5) @@ -26,6 +29,7 @@ def requestJSON(url): def validate_file_path(file_path, preexisting_file=False, writable=False): + """Validate a file path. Checks if the file exists, is a file, and is writable.""" if file_path == "": print("File path is empty.") raise ValueError("Invalid input") @@ -47,6 +51,321 @@ def validate_file_path(file_path, preexisting_file=False, writable=False): def validate_url(url_string): + """Validate a URL string""" result = validators.url(url_string) return False if isinstance(result, ValidationFailure) else result + + +def generate_random_identifier(k): + """Generate a random identifier""" + return "".join(random.choices(string.ascii_lowercase + string.digits, k=k)) + + +def convert_for_datacite(data): + """Converts a dictionary to a format that is compatible with the DOI registration payload""" + doi = f"10.82914/fairhub.{generate_random_identifier(7)}" + creators = [] + titles = [] + subjects = [] + contributors = [] + dates = [] + alternate_identifiers = [] + funding_references = [] + rights_list = [] + descriptions = [] + identifiers_list = [] + related_identifiers = [] + + resource_type = { + "resourceTypeGeneral": data["resourceType"]["resourceTypeGeneral"], + "resourceType": data["resourceType"]["resourceTypeValue"], + } + + identifier_obj = { + "identifier": data["identifier"]["identifierValue"], + "identifierType": data["identifier"]["identifierType"], + } + identifiers_list.append(identifier_obj) + + if "relatedIdentifier" in data: + for related_identifier in data["relatedIdentifier"]: + related_id_obj = { + "relatedIdentifier": related_identifier["relatedIdentifierValue"], + "relatedIdentifierType": related_identifier["relatedIdentifierType"], + "relationType": related_identifier["relationType"], + } + if "relatedMetadataScheme" in related_identifier: + related_id_obj["relatedMetadataScheme"] = related_identifier[ + "relatedMetadataScheme" + ] + + if "schemeURI" in related_identifier: + related_id_obj["schemeUri"] = related_identifier["schemeURI"] + + if "schemeType" in related_identifier: + related_id_obj["schemeType"] = related_identifier["schemeType"] + + if "resourceTypeGeneral" in related_identifier: + related_id_obj["resourceTypeGeneral"] = related_identifier[ + "resourceTypeGeneral" + ] + + related_identifiers.append(related_id_obj) + + if "description" in data: + for description in data["description"]: + description_obj = { + "description": description["descriptionValue"], + "descriptionType": description["descriptionType"], + } + descriptions.append(description_obj) + + for rights in data["rights"]: + rights_obj = {"rights": rights["rightsName"]} + if "rightsURI" in rights: + rights_obj["rightsUri"] = rights["rightsURI"] + if ( + "rightsIdentifier" in rights + and "rightsIdentifierValue" in rights["rightsIdentifier"] + ): + rights_obj["rightsIdentifier"] = rights["rightsIdentifier"][ + "rightsIdentifierValue" + ] + if ( + "rightsIdentifier" in rights + and "rightsIdentifierScheme" in rights["rightsIdentifier"] + ): + rights_obj["rightsIdentifierScheme"] = rights["rightsIdentifier"][ + "rightsIdentifierScheme" + ] + if "rightsIdentifier" in rights and "schemeURI" in rights["rightsIdentifier"]: + rights_obj["schemeUri"] = rights["rightsIdentifier"]["schemeURI"] + rights_list.append(rights_obj) + + if "alternateIdentifier" in data: + for alternate_identifier in data["alternateIdentifier"]: + alternate_identifiers.append( + { + "alternateIdentifier": alternate_identifier[ + "alternateIdentifierValue" + ], + "alternateIdentifierType": alternate_identifier[ + "alternateIdentifierType" + ], + } + ) + + if "date" in data: + for date in data["date"]: + date_obj = { + "date": date["dateValue"], + "dateType": date["dateType"], + } + if "dateInformation" in date: + date_obj["dateInformation"] = date["dateInformation"] + dates.append(date_obj) + + if "contributor" in data: + for contributor in data["contributor"]: + if "affiliation" in contributor: + contributor_affiliations = [] + for affiliation in contributor["affiliation"]: + # TODO: VERIFY BY KEY IS AFFILIATIONVALUE AND NOT NAME + affiliate = { + "name": affiliation["affiliationName"], + } + if ( + "affiliationIdentifier" in affiliation + and "schemeURI" in affiliation["affiliationIdentifier"] + ): + affiliate["schemeUri"] = affiliation["affiliationIdentifier"][ + "schemeURI" + ] + if ( + "affiliationIdentifier" in affiliation + and "affiliationIdentifierScheme" + in affiliation["affiliationIdentifier"] + ): + affiliate["affiliationIdentifierScheme"] = affiliation[ + "affiliationIdentifier" + ]["affiliationIdentifierScheme"] + if ( + "affiliationIdentifier" in affiliation + and "affiliationIdentifierValue" + in affiliation["affiliationIdentifier"] + ): + affiliate["affiliationIdentifier"] = affiliation[ + "affiliationIdentifier" + ]["affiliationIdentifierValue"] + + contributor_affiliations.append(affiliate) + if "nameIdentifier" in contributor: + name_identifiers = [] + for name_identifier in contributor["nameIdentifier"]: + name_identifier = { + "nameIdentifier": name_identifier["nameIdentifierValue"], + "nameIdentifierScheme": name_identifier["nameIdentifierScheme"], + } + if "schemeURI" in name_identifier: + name_identifier["schemeURI"] = name_identifier["schemeURI"] + name_identifiers.append(name_identifier) + + contributor_obj = { + "name": contributor["contributorName"], + "nameType": contributor["nameType"], + "contributorType": contributor["contributorType"], + } + if contributor_affiliations: + contributor_obj["affiliation"] = contributor_affiliations + if name_identifiers: + contributor_obj["nameIdentifiers"] = name_identifiers + + contributors.append(contributor_obj) + + if "subject" in data: + for subject in data["subject"]: + subject_obj = {} + if "classificationCode" in subject: + subject_obj["classificationCode"] = subject["classificationCode"] + if "subjectScheme" in subject: + subject_obj["subjectScheme"] = subject["subjectScheme"] + if "schemeURI" in subject: + subject_obj["schemeUri"] = subject["schemeURI"] + subject_obj["subject"] = subject["subjectValue"] + subjects.append(subject_obj) + + for title in data["title"]: + title_obj = {"title": title["titleValue"]} + if "titleType" in title: + title_obj["titleType"] = title["titleType"] + titles.append(title_obj) + + for creator in data["creator"]: + if "affiliation" in creator: + creator_affiliations = [] + for affiliation in creator["affiliation"]: + affiliate = { + "name": affiliation["affiliationName"], + } + if ( + "affiliationIdentifier" in affiliation + and "schemeURI" in affiliation + ): + affiliate["schemeUri"] = affiliation["affiliationIdentifier"][ + "schemeURI" + ] + if ( + "affiliationIdentifier" in affiliation + and "affiliationIdentifierScheme" in affiliation + ): + affiliate["affiliationIdentifierScheme"] = affiliation[ + "affiliationIdentifier" + ]["affiliationIdentifierScheme"] + if ( + "affiliationIdentifier" in affiliation + and "affiliationIdentifier" in affiliation + ): + affiliate["affiliationIdentifier"] = affiliation[ + "affiliationIdentifier" + ]["affiliationIdentifierValue"] + + creator_affiliations.append(affiliate) + if "nameIdentifier" in creator: + name_identifiers = [] + for name_identifier in creator["nameIdentifier"]: + name_identifier = { + "nameIdentifier": name_identifier["nameIdentifierValue"], + "nameIdentifierScheme": name_identifier["nameIdentifierScheme"], + } + if "schemeURI" in name_identifier: + name_identifier["schemeURI"] = name_identifier["schemeURI"] + name_identifiers.append(name_identifier) + + creator_obj = { + "name": creator["creatorName"], + "nameType": creator["nameType"], + } + if creator_affiliations: + creator_obj["affiliation"] = creator_affiliations + if name_identifiers: + creator_obj["nameIdentifiers"] = name_identifiers + + creators.append(creator_obj) + + if "fundingReference" in data: + for funding_reference in data["fundingReference"]: + funder_obj = {"funderName": funding_reference["funderName"]} + if ( + "funderIdentifier" in funding_reference + and "funderIdentifierValue" in funding_reference["funderIdentifier"] + ): + funder_obj["funderIdentifer"] = funding_reference["funderIdentifier"][ + "funderIdentifierValue" + ] + if ( + "funderIdentifier" in funding_reference + and "funderIdentifierType" in funding_reference["funderIdentifier"] + ): + funder_obj["funderIdentifierType"] = funding_reference[ + "funderIdentifier" + ]["funderIdentifierType"] + + if "awardNumber" in funding_reference: + funder_obj["awardNumber"] = funding_reference["awardNumber"][ + "awardNumberValue" + ] + if "awardURI" in funding_reference["awardNumber"]: + funder_obj["awardURI"] = funding_reference["awardNumber"][ + "awardURI" + ] + if "awardTitle" in funding_reference["awardNumber"]: + funder_obj["awardTitle"] = funding_reference["awardNumber"][ + "awardTitle" + ] + funding_references.append(funder_obj) + + payload = { + "data": { + "type": "dois", + "attributes": { + "event": "publish", + "doi": doi, + "identifiers": identifiers_list, + "creators": creators, + "titles": titles, + "publisher": {"name": data["publisher"]["publisherName"]}, + "publicationYear": data["publicationYear"], + "rightsList": rights_list, + "types": resource_type, + "version": data["version"], + "url": "https://staging.fairhub.io/datasets/3", + }, + } + } + + if "relatedIdentifier" in data and len(data["relatedIdentifier"]) > 0: + payload["data"]["attributes"]["relatedIdentifiers"] = data["relatedIdentifier"] + if "size" in data and len(data["size"]) > 0: + payload["data"]["attributes"]["sizes"] = data["size"] + if "format" in data and len(data["format"]) > 0: + payload["data"]["attributes"]["formats"] = data["format"] + if "language" in data and len(data["language"]) > 0: + payload["data"]["attributes"]["language"] = data["language"] + + if len(descriptions) > 0: + payload["data"]["attributes"]["description"] = descriptions + if len(alternate_identifiers) > 0: + payload["data"]["attributes"]["alternateIdentifiers"] = alternate_identifiers + if len(funding_references) > 0: + payload["data"]["attributes"]["fundingReferences"] = funding_references + if len(contributors) > 0: + payload["data"]["attributes"]["contributors"] = contributors + if len(subjects) > 0: + payload["data"]["attributes"]["subjects"] = subjects + if len(dates) > 0: + payload["data"]["attributes"]["dates"] = dates + if len(related_identifiers) > 0: + payload["data"]["attributes"]["relatedIdentifiers"] = related_identifiers + + return payload diff --git a/pyfairdatatools/validate.py b/pyfairdatatools/validate.py index 98fc7d6..f4309b3 100644 --- a/pyfairdatatools/validate.py +++ b/pyfairdatatools/validate.py @@ -1,12 +1,13 @@ import json import os +import yaml from jsonschema import ValidationError, validate # from . import utils -def validate_dataset_description(data): # sourcery skip: extract-method +def validate_dataset_description(data, verbose=False): # sourcery skip: extract-method """Validate a dataset description against the schema. Args: @@ -29,7 +30,7 @@ def validate_dataset_description(data): # sourcery skip: extract-method validate(instance=data, schema=schema) # validate the language code - if "Language" in data: + if "language" in data: with open( os.path.join(os.path.dirname(__file__), "assets", "languages.json"), encoding="utf-8", @@ -37,54 +38,38 @@ def validate_dataset_description(data): # sourcery skip: extract-method list_of_language_codes = json.load(f) valid = any( - language["code"] == data["Language"] + language["code"] == data["language"] for language in list_of_language_codes ) if not valid: - print("Language code is invalid.") + print("language code is invalid.") return False - Contributors = data["Contributor"] + if "relatedIdentifier" in data: + related_identifiers = data["relatedIdentifier"] - for Contributor in Contributors: - if "affilation" in Contributor: - affiliations = Contributor["affilation"] - - for affiliation in affiliations: - if ( - "affiliationValue" not in affiliation - and "affiliationIdentifier" not in affiliation - ): - print("affiliationValue or affiliationIdentifier is required.") + for related_identifier in related_identifiers: + if related_identifier["relationType"] in [ + "IsMetadataFor", + "HasMetadata", + ]: + if "relatedMetadataScheme" not in related_identifier: + print( + "relatedMetadataScheme is required for IsMetadataFor and HasMetadata relation types." + ) return False - if "affiliationIdentifier" in affiliation: - if "affiliationIdentifierScheme" not in affiliation: - print( - "affiliationIdentifierScheme is required if affiliationIdentifier is provided." # pylint: disable=line-too-long - ) - return False - - Creators = data["Creator"] - - for Creator in Creators: - if "affilation" in Creator: - affiliations = Creator["affilation"] - - for affiliation in affiliations: - if ( - "affiliationValue" not in affiliation - and "affiliationIdentifier" not in affiliation - ): - print("affiliationValue or affiliationIdentifier is required.") + if "schemeURI" not in related_identifier: + print( + "schemeURI is required for IsMetadataFor and HasMetadata relation types." + ) return False - if "affiliationIdentifier" in affiliation: - if "affiliationIdentifierScheme" not in affiliation: - print( - "affiliationIdentifierScheme is required if affiliationIdentifier is provided." # pylint: disable=line-too-long - ) - return False + if "schemeType" not in related_identifier: + print( + "schemeType is required for IsMetadataFor and HasMetadata relation types." + ) + return False return True except ValidationError as e: @@ -98,7 +83,7 @@ def validate_dataset_description(data): # sourcery skip: extract-method raise error -def validate_study_description(data): # sourcery skip: extract-method +def validate_study_description(data): # sourcery skip: extract-method, low-code-quality """Validate a study description against the schema.""" schema = {} @@ -114,185 +99,69 @@ def validate_study_description(data): # sourcery skip: extract-method try: validate(instance=data, schema=schema) - OrgStudyIdType = data["IdentificationModule"]["OrgStudyIdInfo"][ - "OrgStudyIdType" - ] - - if OrgStudyIdType in [ - "Other Grant/Funding Number", - "Registry Identifier", - "Other Identifier", - ]: - # check if the OrgStudyIdDomain key exists and is not empty - if "OrgStudyIdDomain" not in data["IdentificationModule"]["OrgStudyIdInfo"]: - print("OrgStudyIdDomain is required.") - return False - - OrgStudyIdDomain = data["IdentificationModule"]["OrgStudyIdInfo"][ - "OrgStudyIdDomain" - ] - - if OrgStudyIdDomain is None or OrgStudyIdDomain == "": - print("A value for OrgStudyIdDomain is required.") - return False - - if "SecondaryIdInfoList" in data["IdentificationModule"]: - SecondaryIdInfoList = data["IdentificationModule"]["SecondaryIdInfoList"] - - for SecondaryIdInfo in SecondaryIdInfoList: - SecondaryIdType = SecondaryIdInfo["SecondaryIdType"] - - if SecondaryIdType in [ - "Other Grant/Funding Number", - "Registry Identifier", - "Other Identifier", - ]: - # check if the SecondaryIdDomain key exists and is not empty - if "SecondaryIdDomain" not in SecondaryIdInfo: - print("SecondaryIdDomain is required.") - return False - - SecondaryIdDomain = SecondaryIdInfo["SecondaryIdDomain"] - - if SecondaryIdDomain is None or SecondaryIdDomain == "": - print("A value for SecondaryIdDomain is required") - return False + statusModule = data["statusModule"] - OverallStatus = data["StatusModule"]["OverallStatus"] + overallStatus = statusModule["overallStatus"] - if OverallStatus in ["Suspended", "Completed", "Terminated"]: - # check if the WhyStopped key exists and is not empty - if "WhyStopped" not in data["StatusModule"]: - print("WhyStopped is required.") - return False - - WhyStopped = data["StatusModule"]["WhyStopped"] - - if WhyStopped is None or WhyStopped == "": - print("A value for WhyStopped is required.") - return False - - ResponsiblePartyType = data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyType" - ] - - if ResponsiblePartyType in ["Principal Investigator", "Sponsor-Investigator"]: - # check if the ResponsiblePartyInvestigatorFullName key exists - # and is not empty - if ( - "ResponsiblePartyInvestigatorFullName" - not in data["SponsorCollaboratorsModule"]["ResponsibleParty"] - ): - print("ResponsiblePartyInvestigatorFullName is required.") - return False - - ResponsiblePartyInvestigatorFullName = data["SponsorCollaboratorsModule"][ - "ResponsibleParty" - ]["ResponsiblePartyInvestigatorFullName"] - - if ( - ResponsiblePartyInvestigatorFullName is None - or ResponsiblePartyInvestigatorFullName == "" - ): - print("A value for ResponsiblePartyInvestigatorFullName is required.") - return False - - # check if the ResponsiblePartyInvestigatorTitle key exists and is not empty - if ( - "ResponsiblePartyInvestigatorTitle" - not in data["SponsorCollaboratorsModule"]["ResponsibleParty"] - ): - print("ResponsiblePartyInvestigatorTitle is required.") - return False - - ResponsiblePartyInvestigatorTitle = data["SponsorCollaboratorsModule"][ - "ResponsibleParty" - ]["ResponsiblePartyInvestigatorTitle"] - - if ( - ResponsiblePartyInvestigatorTitle is None - or ResponsiblePartyInvestigatorTitle == "" - ): - print("A value for ResponsiblePartyInvestigatorTitle is required.") - return False - - # check if the ResponsiblePartyInvestigatorAffiliation key exists - # and is not empty - if ( - "ResponsiblePartyInvestigatorAffiliation" - not in data["SponsorCollaboratorsModule"]["ResponsibleParty"] - ): - print("ResponsiblePartyInvestigatorAffiliation is required.") - return False - - ResponsiblePartyInvestigatorAffiliation = data[ - "SponsorCollaboratorsModule" - ]["ResponsibleParty"]["ResponsiblePartyInvestigatorAffiliation"] - - if ( - ResponsiblePartyInvestigatorAffiliation is None - or ResponsiblePartyInvestigatorAffiliation == "" - ): + if overallStatus in ["Withdrawn", "Terminated", "Suspended"]: + if "whyStopped" not in statusModule: print( - "A value for ResponsiblePartyInvestigatorAffiliation is required." + "whyStopped is required for Withdrawn, Terminated, and Suspended overallStatus." ) return False - StudyType = data["DesignModule"]["StudyType"] + studyType = data["designModule"]["studyType"] - if StudyType == "Interventional": - ArmGroupList = data["ArmsInterventionsModule"]["ArmGroupList"] + if studyType == "Interventional": + armGroupList = data["armsInterventionsModule"]["armGroupList"] - for ArmGroup in ArmGroupList: - if "ArmGroupType" not in ArmGroup: + for armGroup in armGroupList: + if "armGroupType" not in armGroup: print( - "ArmGroupType is required is required for interventional studies." # pylint: disable=line-too-long + "armGroupType is required is required for interventional studies." # pylint: disable=line-too-long ) return False - # check if the HealthyVolunteers key exists - if "HealthyVolunteers" not in data["EligibilityModule"]: - print("HealthyVolunteers is required for interventional studies.") - return False - - if StudyType == "Observational": + elif studyType == "Observational": # check if the StudyPopulation key exists and is not empty - if "StudyPopulation" not in data["EligibilityModule"]: - print("StudyPopulation is required for observational studies.") + if "studyPopulation" not in data["eligibilityModule"]: + print("studyPopulation is required for observational studies.") return False - StudyPopulation = data["EligibilityModule"]["StudyPopulation"] + studyPopulation = data["eligibilityModule"]["studyPopulation"] - if StudyPopulation is None or StudyPopulation == "": + if studyPopulation is None or studyPopulation == "": print( - "A value for StudyPopulation is required for observational studies." + "A value for studyPopulation is required for observational studies." ) return False # check if the SamplingMethod key exists - if "SamplingMethod" not in data["EligibilityModule"]: - print("SamplingMethod is required for observational studies.") + if "samplingMethod" not in data["eligibilityModule"]: + print("samplingMethod is required for observational studies.") return False - if ("CentralContactList" not in data["ContactsLocationsModule"]) or ( - "CentralContactList" in data["ContactsLocationsModule"] - and len(data["ContactsLocationsModule"]["CentralContactList"]) == 0 + if ( + "centralContactList" not in data["contactsLocationsModule"] + or len(data["contactsLocationsModule"]["centralContactList"]) == 0 ): - LocationList = data["ContactsLocationsModule"]["LocationList"] + locationList = data["contactsLocationsModule"]["locationList"] - for Location in LocationList: + for location in locationList: if ( - "LocationContactList" not in Location - or len(Location["LocationContactList"]) == 0 + "locationContactList" not in location + or len(location["locationContactList"]) == 0 ): print( - "LocationContactList is required if no Central Contact is provided." # pylint: disable=line-too-long + "locationContactList is required if no Central Contact is provided." # pylint: disable=line-too-long ) return False return True except ValidationError as e: - print(e.schema["error_msg"] if "error_msg" in e.schema else e.message) + print(f" Validation Error: {e.message}") + print(f"→ Field Path: {'.'.join(str(p) for p in e.path)}") + print(f"→ Schema Rule Path: {'.'.join(str(p) for p in e.schema_path)}") return False except Exception as error: print(error) @@ -436,3 +305,48 @@ def path_to_dict(path): except Exception as error: print(error) raise error + + +def validate_datatype_dictionary(data): + """Validate a datatype description against the scheme. + + Args: + data (list): The datatype description to validate + Returns: + bool: True if the datatype description is valid, False otherwise + """ + # Import the yaml file from the schemas folder + with open( + os.path.join( + os.path.dirname(__file__), + "assets", + "datatype_dictionary.yaml", + ), + encoding="utf-8", + ) as f: + schema = yaml.safe_load(f) + + try: + # create a list of code_name and aliases from schema to validate against + code_name_list = [ + code_name["code_name"] for code_name in schema["datatype_dictionary"] + ] + code_name_list += [ + alias + for code_name in schema["datatype_dictionary"] + if "aliases" in code_name + for alias in code_name["aliases"] + ] + + for entry in data: + if entry not in code_name_list: + print(f"code_name {entry} is not a valid code_name or alias.") + return False + + return True + except ValidationError as e: + print(e.schema["error_msg"] if "error_msg" in e.schema else e.message) + return False + except Exception as error: + print(error) + raise error diff --git a/pyproject.toml b/pyproject.toml index 0da8c82..6a281f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "pyfairdatatools" -version = "1.0.2" +version = "1.2.0b9" description = "Tools for AI-READI" packages = [{ include = "pyfairdatatools" }] @@ -16,7 +16,6 @@ repository = "https://github.com/AI-READI/pyfairdatatools" keywords = [] classifiers = [ - # TODO: update this list to match your application: https://pypi.org/pypi?%3Aaction=list_classifiers "Development Status :: 1 - Planning", "Intended Audience :: Developers", "License :: OSI Approved", @@ -33,7 +32,6 @@ classifiers = [ python = "^3.8" urllib3 = "<2.0" -# TODO: Remove these and add your library's requirements click = "*" minilog = "*" jsonschema = "^4.17.3" @@ -42,9 +40,11 @@ types-requests = "^2.30.0.0" pymdown-extensions = "^10.0.1" validators = "^0.20.0" art = "^6.0" +pyyaml = "^6.0.1" +types-pyyaml = "^6.0.12.12" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] # Formatters black = "^22.1" @@ -78,16 +78,12 @@ sniffer = "*" MacFSEvents = { version = "*", platform = "darwin" } pync = { version = "*", platform = "darwin" } ipython = "^7.12.0" +poethepoet = "^0.20.0" [tool.poetry.scripts] pyfairdatatools = "pyfairdatatools.cli:main" - -[tool.poetry.group.dev.dependencies] -poethepoet = "^0.20.0" -jupyter = "^1.0.0" - [tool.poe.tasks] docs = "mkdocs serve" @@ -103,10 +99,13 @@ pylint = "pylint pyfairdatatools tests --rcfile=.pylint.ini" precommit = ["format", "typecheck", "pylint"] -test = "pytest -rx" +test = "pytest -rx -W ignore::DeprecationWarning" +test_with_capture = "pytest -s -W ignore::DeprecationWarning" jupyter = "jupyter notebook" +sync_schemas = "python ./dev/pull_schemas.py" + [tool.black] quiet = true diff --git a/tests/test_generate.py b/tests/test_generate.py index 0588afc..6651969 100644 --- a/tests/test_generate.py +++ b/tests/test_generate.py @@ -1,4 +1,5 @@ """Unit tests for pyfairdatatools.generate module.""" + # pylint: disable=redefined-outer-name,unused-variable,expression-not-assigned,singleton-comparison # noqa: E501 import json @@ -7,6 +8,7 @@ from pyfairdatatools.generate import ( generate_changelog_file, generate_dataset_description, + generate_datatype_file, generate_license_file, generate_readme, generate_study_description, @@ -16,11 +18,12 @@ class TestGenerateDatasetDescription: def test_valid_dataset_description(self, tmp_path): data = { - "Identifier": { + "schema": "https://schema.aireadi.org/v0.1.0/dataset_description.json", + "identifier": { "identifierValue": "10.5281/zenodo.1234567", "identifierType": "DOI", }, - "Title": [ + "title": [ { "titleValue": "Main Title", }, @@ -29,14 +32,14 @@ def test_valid_dataset_description(self, tmp_path): "titleType": "Subtitle", }, ], - "Version": "1.0.0", - "AlternateIdentifier": [ + "version": "1.0.0", + "alternateIdentifier": [ { "alternateIdentifierValue": "10.5281/zenodo.1234567", "alternateIdentifierType": "DOI", } ], - "Creator": [ + "creator": [ { "creatorName": "Doe, John", "nameType": "Personal", @@ -49,9 +52,12 @@ def test_valid_dataset_description(self, tmp_path): ], "affiliation": [ { - "affiliationIdentifier": "https://ror.org/123456789", - "affiliationIdentifierScheme": "ROR", - "schemeURI": "https://ror.org", + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, } ], }, @@ -67,7 +73,7 @@ def test_valid_dataset_description(self, tmp_path): ], }, ], - "Contributor": [ + "contributor": [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -81,9 +87,12 @@ def test_valid_dataset_description(self, tmp_path): ], "affiliation": [ { - "affiliationIdentifier": "https://ror.org/123456789", - "affiliationIdentifierScheme": "ROR", - "schemeURI": "https://ror.org", + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, } ], }, @@ -100,23 +109,19 @@ def test_valid_dataset_description(self, tmp_path): ], }, ], - "PublicationYear": "2023", - "Date": [ + "publicationYear": "2023", + "date": [ { "dateValue": "2023-01-01", "dateType": "Collected", "dateInformation": "Some information", } ], - "ResourceType": { + "resourceType": { "resourceTypeValue": "Diabetes", "resourceTypeGeneral": "Dataset", }, - "DatasetRecordKeys": { - "keysType": "Anonymised", - "keysDetails": "Some details", - }, - "DatasetDeIdentLevel": { + "datasetDeIdentLevel": { "deIdentType": "NoDeIdentification", "deIdentDirect": True, "deIdentHIPAA": True, @@ -125,7 +130,7 @@ def test_valid_dataset_description(self, tmp_path): "deIdentKAnon": True, "deIdentDetails": "Some details", }, - "DatasetConsent": { + "datasetConsent": { "consentType": "NoRestriction", "consentNoncommercial": True, "consentGeogRestrict": True, @@ -134,52 +139,69 @@ def test_valid_dataset_description(self, tmp_path): "consentNoMethods": True, "consentsDetails": "Some details", }, - "Description": [ + "description": [ {"descriptionValue": "Some description", "descriptionType": "Abstract"}, {"descriptionValue": "Some description", "descriptionType": "Methods"}, ], - "Language": "en", - "RelatedIdentifier": [ + "language": "en", + "relatedIdentifier": [ { "relatedIdentifierValue": "10.5281/zenodo.1234567", "relatedIdentifierType": "DOI", - "relationType": "HasMetadata", + "relationType": "IsCitedBy", "relatedMetadataScheme": "DataCite", - "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", + "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", # noqa: E501 pylint: disable=line-too-long "schemeType": "DOI", "resourceTypeGeneral": "Dataset", } ], - "Subject": [ + "subject": [ { "subjectValue": "Diabetes", - "subjectScheme": "MeSH", - "schemeURI": "https://www.nlm.nih.gov/mesh/", - "valueURI": "https://www.nlm.nih.gov/mesh/1234567", - "classificationCode": "E11.9", + "subjectIdentifier": { + "classificationCode": "E11.9", + "subjectScheme": "MeSH", + "schemeURI": "https://www.nlm.nih.gov/mesh/", + "valueURI": "https://www.nlm.nih.gov/mesh/1234567", + }, } ], - "ManagingOrganisation": { - "name": "Test Organisation", - "rorId": "https://ror.org/123456789", + "managingOrganization": { + "name": "Test Organization", + "managingOrganizationIdentifier": { + "managingOrganizationIdentifierValue": "04z8jg394", + "managingOrganizationScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, }, - "AccessType": "PublicOnScreenAccess", - "AccessDetails": { + "accessType": "PublicOnScreenAccess", + "accessDetails": { "description": "Some description", "url": "https://example.com", "urlLastChecked": "2021-01-01", }, - "Rights": [ + "rights": [ { - "rightsValue": "CC0-1.0", + "rightsName": "CC0-1.0", "rightsURI": "https://creativecommons.org/publicdomain/zero/1.0/", - "rightsIdentifier": "CC0-1.0", - "rightsIdentifierScheme": "SPDX", + "rightsIdentifier": { + "rightsIdentifierValue": "CC0-1.0", + "rightsIdentifierScheme": "SPDX", + "schemeURI": "https://spdx.org/licenses/", + }, } ], - "Publisher": "GitHub", - "Size": ["15 pages", "15 MB"], - "FundingReference": [ + "publisher": { + "publisherName": "Test Publisher", + "publisherIdentifier": { + "publisherIdentifierValue": "04z8jg394", + "publisherIdentifierScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, + }, + "size": ["15 pages", "15 MB"], + "format": ["application/pdf", "text/xml", "MOPG", "nifti"], + "fundingReference": [ { "funderName": "Test Funder", "funderIdentifier": { @@ -194,47 +216,6 @@ def test_valid_dataset_description(self, tmp_path): "awardTitle": "Test Award", } ], - "RelatedItem": [ - { - "relatedItemType": "Book", - "relationType": "IsMetadataFor", - "relatedItemIdentifier": [ - { - "relatedItemIdentifierValue": "10.5281/zenodo.1234567", - "relatedItemIdentifierType": "DOI", - "relatedMetadataScheme": "DataCite", - "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", - "schemeType": "DDT", - } - ], - "creator": [ - { - "creatorName": "Doe, John", - "nameType": "Personal", - } - ], - "title": [ - { - "titleValue": "Test title", - } - ], - "publicationYear": "2021", - "volume": "1", - "issue": "1", - "number": {"numberValue": "1", "numberType": "Article"}, - "firstPage": "1", - "lastPage": "15", - "publisher": "Test Publisher", - "edition": "1", - "contributor": [ - { - "contributorType": "Editor", - "contributorName": "Doe, John", - "nameType": "Personal", - } - ], - } - ], } file = tmp_path / "dataset_description.json" @@ -260,157 +241,148 @@ def test_valid_dataset_description(self, tmp_path): class TestGenerateStudyDescription: def test_observational_study_description(self, tmp_path): data = { - "IdentificationModule": { - "OrgStudyIdInfo": { - "OrgStudyId": "RandomStudyId", - "OrgStudyIdType": "Registry Identifier", - "OrgStudyIdDomain": "ClinicalTrials.gov", - "OrgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", + "schema": "https://schema.aireadi.org/v0.1.0/study_description.json", + "identificationModule": { + "officialTitle": "Test Title", + "acronym": "TT", + "orgStudyIdInfo": { + "orgStudyId": "RandomStudyId", + "orgStudyIdType": "Registry Identifier", + "orgStudyIdDomain": "ClinicalTrials.gov", + "orgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", }, - "SecondaryIdInfoList": [ + "secondaryIdInfoList": [ { - "SecondaryId": "SomeID", - "SecondaryIdType": "Other Identifier", - "SecondaryIdDomain": "Other", - "SecondaryIdLink": "https://example.com", + "secondaryId": "SomeID", + "secondaryIdType": "Other Identifier", + "secondaryIdDomain": "Other", + "secondaryIdLink": "https://example.com", } ], }, - "StatusModule": { - "OverallStatus": "Suspended", - "WhyStopped": "Study stopped due to lack of funding", - "StartDateStruct": { - "StartDate": "July 07, 2023", - "StartDateType": "Actual", + "statusModule": { + "overallStatus": "Suspended", + "whyStopped": "Study stopped due to lack of funding", + "startDateStruct": { + "startDate": "2023-06", + "startDateType": "Actual", }, - "CompletionDateStruct": { - "CompletionDate": "July 08, 2024", - "CompletionDateType": "Actual", + "completionDateStruct": { + "completionDate": "2024-06", + "completionDateType": "Actual", }, }, - "SponsorCollaboratorsModule": { - "ResponsibleParty": { - "ResponsiblePartyType": "Principal Investigator", - "ResponsiblePartyInvestigatorFullName": "Harper Spiller", - "ResponsiblePartyInvestigatorTitle": "Principal Investigator", - "ResponsiblePartyInvestigatorAffiliation": "White Lotus", + "sponsorCollaboratorsModule": { + "responsibleParty": { + "responsiblePartyType": "Principal Investigator", + "responsiblePartyInvestigatorFirstName": "Harper", + "responsiblePartyInvestigatorLastName": "Spiller", + "responsiblePartyInvestigatorTitle": "Principal Investigator", + "responsiblePartyInvestigatorAffiliation": { + "responsiblePartyInvestigatorAffiliationName": "White Lotus", + }, }, - "LeadSponsor": {"LeadSponsorName": "Harper Spiller"}, - "CollaboratorList": [ - {"CollaboratorName": "Nicole Mossbacher"}, - {"CollaboratorName": "Olivia Mossbacher"}, + "leadSponsor": {"leadSponsorName": "Harper Spiller"}, + "collaboratorList": [ + {"collaboratorName": "Nicole Mossbacher"}, + {"collaboratorName": "Olivia Mossbacher"}, ], }, - "OversightModule": { - "OversightHasDMC": "No", + "oversightModule": { + "isFDARegulatedDrug": "No", + "isFDARegulatedDevice": "No", + "humanSubjectReviewStatus": "Request not yet submitted", + "oversightHasDMC": "No", }, - "DescriptionModule": { - "BriefSummary": "This is a brief summary", - "DetailedDescription": "This is a detailed description", + "descriptionModule": { + "briefSummary": "This is a brief summary", + "detailedDescription": "This is a detailed description", }, - "ConditionsModule": { - "ConditionList": ["Condition 1", "Condition 2"], - "KeywordList": ["Keyword 1", "Keyword 2"], + "conditionsModule": { + "conditionList": [ + {"conditionName": "Condition 1"}, + {"conditionName": "Condition 2"}, + ], + "keywordList": [ + {"keywordValue": "Keyword 1"}, + {"keywordValue": "Keyword 2"}, + ], }, - "DesignModule": { - "StudyType": "Observational", - "DesignInfo": { - "DesignObservationalModelList": ["Cohort"], - "DesignTimePerspectiveList": ["Prospective"], + "designModule": { + "studyType": "Observational", + "designInfo": { + "designObservationalModelList": ["Cohort"], + "designTimePerspectiveList": ["Prospective"], }, - "BioSpec": { - "BioSpecRetention": "Samples With DNA", - "BioSpecDescription": "This is a description of the biospecs", + "bioSpec": { + "bioSpecRetention": "Samples With DNA", + "bioSpecDescription": "This is a description of the biospecs", }, - "EnrollmentInfo": { - "EnrollmentCount": "34", - "EnrollmentType": "Anticipated", + "enrollmentInfo": { + "enrollmentCount": "34", + "enrollmentType": "Anticipated", }, - "TargetDuration": "4 Years", - "NumberGroupsCohorts": "1", + "targetDuration": "4 Years", + "numberGroupsCohorts": "1", + "isPatientRegistry": "Yes", }, - "ArmsInterventionsModule": { - "ArmGroupList": [ - {"ArmGroupLabel": "Arm 1", "ArmGroupDescription": "Experimental"} + "armsInterventionsModule": { + "armGroupList": [ + {"armGroupLabel": "Arm 1", "armGroupDescription": "Experimental"} ], - "InterventionList": [ + "interventionList": [ { - "InterventionType": "Drug", - "InterventionName": "Drug 1", - "InterventionDescription": "description of the intervention", - "InterventionArmGroupLabelList": ["Arm 1"], - "InterventionOtherNameList": ["Other Name 1"], + "interventionType": "Drug", + "interventionName": "Drug 1", + "interventionDescription": "description of the intervention", + "interventionOtherNameList": ["Other Name 1"], }, ], }, - "EligibilityModule": { - "Gender": "All", - "GenderBased": "No", - "MinimumAge": "18 Years", - "MaximumAge": "65 Years", - "EligibilityCriteria": "This is the eligibility criteria", - "StudyPopulation": "This is the study population", - "SamplingMethod": "Non-Probability Sample", - }, - "ContactsLocationsModule": { - "CentralContactList": [ - { - "CentralContactName": "Ethan Spiller", - "CentralContactAffiliation": "White Lotus", - "CentralContactPhone": "805-555-5555", - "CentralContactPhoneExt": "123", - "CentralContactEMail": "e.spiller@hbo.com", - } - ], - "OverallOfficialList": [ - { - "OverallOfficialName": "Daphne Sullivan", - "OverallOfficialAffiliation": "White Lotus", - "OverallOfficialRole": "Study Principal Investigator", - } - ], - "LocationList": [ - { - "LocationFacility": "White Lotus", - "LocationStatus": "Recruiting", - "LocationCity": "Kihei", - "LocationState": "Hawaii", - "LocationZip": "96753", - "LocationCountry": "United States", - } - ], - }, - "IPDSharingStatementModule": { - "IPDSharing": "Yes", - "IPDSharingDescription": "description of the IPD sharing statement", - "IPDSharingInfoTypeList": [ - "Study Protocol", - "Statistical Analysis Plan (SAP)", - ], - "IPDSharingTimeFrame": "Beginning 9 Months and ending 36 months", - "IPDSharingAccessCriteria": "This is the IPD sharing access criteria", - "IPDSharingURL": "https://example.com", + "eligibilityModule": { + "sex": "All", + "genderBased": "No", + "minimumAge": "18 Years", + "maximumAge": "65 Years", + "eligibilityCriteria": { + "eligibilityCriteriaInclusion": ["crietia 1", "crietia 2"], + "eligibilityCriteriaExclusion": ["crietia 1", "crietia 2"], + }, + "studyPopulation": "This is the study population", + "healthyVolunteers": "No", + "samplingMethod": "Non-Probability Sample", }, - "ReferencesModule": { - "ReferenceList": [ + "contactsLocationsModule": { + "centralContactList": [ { - "ReferenceID": "12345678", - "ReferenceType": "Yes", - "ReferenceCitation": "This is a reference citation", + "centralContactFirstName": "Ethan", + "centralContactLastName": "Spiller", + "centralContactAffiliation": { + "centralContactAffiliationName": "White Lotus", + }, + "centralContactPhone": "805-555-5555", + "centralContactPhoneExt": "123", + "centralContactEMail": "e.spiller@hbo.com", } ], - "SeeAlsoLinkList": [ + "overallOfficialList": [ { - "SeeAlsoLinkLabel": "This is a link label", - "SeeAlsoLinkURL": "https://example.com", + "overallOfficialFirstName": "Daphne", + "overallOfficialLastName": "Sullivan", + "overallOfficialAffiliation": { + "overallOfficialAffiliationName": "White Lotus", + }, + "overallOfficialRole": "Study Principal Investigator", } ], - "AvailIPDList": [ + "locationList": [ { - "AvailIPDId": "123456", - "AvailIPDType": "Clinical Study Report", - "AvailIPDURL": "https://example.com", - "AvailIPDComment": "This is the avail IPD access criteria", + "locationFacility": "White Lotus", + "locationStatus": "Recruiting", + "locationCity": "Kihei", + "locationState": "Hawaii", + "locationZip": "96753", + "locationCountry": "United States", } ], }, @@ -429,170 +401,159 @@ def test_observational_study_description(self, tmp_path): file = tmp_path / "study_description.xml" file_type = "xml" - generate_study_description(data, file, file_type) + # generate_study_description(data, file, file_type) # TODO: add validation of the XML file def test_interventional_study_description(self, tmp_path): data = { - "IdentificationModule": { - "OrgStudyIdInfo": { - "OrgStudyId": "RandomStudyId", - "OrgStudyIdType": "Registry Identifier", - "OrgStudyIdDomain": "ClinicalTrials.gov", - "OrgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", + "schema": "https://schema.aireadi.org/v0.1.0/study_description.json", + "identificationModule": { + "officialTitle": "Test Title", + "acronym": "TT", + "orgStudyIdInfo": { + "orgStudyId": "RandomStudyId", + "orgStudyIdType": "Registry Identifier", + "orgStudyIdDomain": "ClinicalTrials.gov", + "orgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", }, - "SecondaryIdInfoList": [ + "secondaryIdInfoList": [ { - "SecondaryId": "SomeID", - "SecondaryIdType": "Other Identifier", - "SecondaryIdDomain": "Other", - "SecondaryIdLink": "https://example.com", + "secondaryId": "SomeID", + "secondaryIdType": "Other Identifier", + "secondaryIdDomain": "Other", + "secondaryIdLink": "https://example.com", } ], }, - "StatusModule": { - "OverallStatus": "Suspended", - "WhyStopped": "Study stopped due to lack of funding", - "StartDateStruct": { - "StartDate": "July 07, 2023", - "StartDateType": "Actual", + "statusModule": { + "overallStatus": "Suspended", + "whyStopped": "Study stopped due to lack of funding", + "startDateStruct": { + "startDate": "2023-06", + "startDateType": "Actual", }, - "CompletionDateStruct": { - "CompletionDate": "July 08, 2024", - "CompletionDateType": "Actual", + "completionDateStruct": { + "completionDate": "2024-06", + "completionDateType": "Actual", }, }, - "SponsorCollaboratorsModule": { - "ResponsibleParty": { - "ResponsiblePartyType": "Principal Investigator", - "ResponsiblePartyInvestigatorFullName": "Harper Spiller", - "ResponsiblePartyInvestigatorTitle": "Principal Investigator", - "ResponsiblePartyInvestigatorAffiliation": "White Lotus", + "sponsorCollaboratorsModule": { + "responsibleParty": { + "responsiblePartyType": "Principal Investigator", + "responsiblePartyInvestigatorFirstName": "Harper", + "responsiblePartyInvestigatorLastName": "Spiller", + "responsiblePartyInvestigatorTitle": "Principal Investigator", + "responsiblePartyInvestigatorAffiliation": { + "responsiblePartyInvestigatorAffiliationName": "White Lotus", + }, }, - "LeadSponsor": {"LeadSponsorName": "Harper Spiller"}, - "CollaboratorList": [ - {"CollaboratorName": "Nicole Mossbacher"}, - {"CollaboratorName": "Olivia Mossbacher"}, + "leadSponsor": {"leadSponsorName": "Harper Spiller"}, + "collaboratorList": [ + {"collaboratorName": "Nicole Mossbacher"}, + {"collaboratorName": "Olivia Mossbacher"}, ], }, - "OversightModule": { - "OversightHasDMC": "No", + "oversightModule": { + "isFDARegulatedDrug": "No", + "isFDARegulatedDevice": "No", + "humanSubjectReviewStatus": "Request not yet submitted", + "oversightHasDMC": "No", }, - "DescriptionModule": { - "BriefSummary": "This is a brief summary", - "DetailedDescription": "This is a detailed description", + "descriptionModule": { + "briefSummary": "This is a brief summary", + "detailedDescription": "This is a detailed description", }, - "ConditionsModule": { - "ConditionList": ["Condition 1", "Condition 2"], - "KeywordList": ["Keyword 1", "Keyword 2"], + "conditionsModule": { + "conditionList": [ + {"conditionName": "Condition 1"}, + {"conditionName": "Condition 2"}, + ], + "keywordList": [ + {"keywordValue": "Keyword 1"}, + {"keywordValue": "Keyword 2"}, + ], }, - "DesignModule": { - "StudyType": "Interventional", - "DesignInfo": { - "DesignAllocation": "Randomized", - "DesignInterventionModel": "Prevention", - "DesignInterventionModelDescription": "description", - "DesignPrimaryPurpose": "Parallel Assignment", - "DesignMaskingInfo": { - "DesignMasking": "Blinded (no details)", - "DesignMaskingDescription": "description of the design masking", - "DesignWhoMaskedList": ["Participant", "Care Provider"], + "designModule": { + "studyType": "Interventional", + "designInfo": { + "designAllocation": "Randomized", + "designInterventionModel": "Prevention", + "designInterventionModelDescription": "description", + "designPrimaryPurpose": "Parallel Assignment", + "designMaskingInfo": { + "designMasking": "Blinded (no details)", + "designMaskingDescription": "description of the design masking", + "designWhoMaskedList": ["Participant", "Care Provider"], }, }, - "PhaseList": ["Phase 1/2"], - "EnrollmentInfo": { - "EnrollmentCount": "34", - "EnrollmentType": "Anticipated", + "phaseList": ["Phase 1/2"], + "enrollmentInfo": { + "enrollmentCount": "34", + "enrollmentType": "Anticipated", }, - "NumberArms": "1", + "numberArms": "1", }, - "ArmsInterventionsModule": { - "ArmGroupList": [ + "armsInterventionsModule": { + "armGroupList": [ { - "ArmGroupLabel": "Arm 1", - "ArmGroupType": "Placebo Comparator", - "ArmGroupDescription": "Experimental", - "ArmGroupInterventionList": ["Drug 1"], + "armGroupLabel": "Arm 1", + "armGroupType": "Placebo Comparator", + "armGroupDescription": "Experimental", + "armGroupInterventionList": ["Drug 1"], } ], - "InterventionList": [ + "interventionList": [ { - "InterventionType": "Drug", - "InterventionName": "Drug 1", - "InterventionDescription": "description of the intervention", - "InterventionArmGroupLabelList": ["Arm 1"], - "InterventionOtherNameList": ["Other Name 1"], + "interventionType": "Drug", + "interventionName": "Drug 1", + "interventionDescription": "description of the intervention", + "interventionOtherNameList": ["Other Name 1"], }, ], }, - "EligibilityModule": { - "Gender": "All", - "GenderBased": "No", - "MinimumAge": "18 Years", - "MaximumAge": "65 Years", - "HealthyVolunteers": "No", - "EligibilityCriteria": "This is the eligibility criteria", - }, - "ContactsLocationsModule": { - "CentralContactList": [ - { - "CentralContactName": "Ethan Spiller", - "CentralContactAffiliation": "White Lotus", - "CentralContactPhone": "805-555-5555", - "CentralContactPhoneExt": "123", - "CentralContactEMail": "e.spiller@hbo.com", - } - ], - "OverallOfficialList": [ - { - "OverallOfficialName": "Daphne Sullivan", - "OverallOfficialAffiliation": "White Lotus", - "OverallOfficialRole": "Study Principal Investigator", - } - ], - "LocationList": [ - { - "LocationFacility": "White Lotus", - "LocationStatus": "Recruiting", - "LocationCity": "Kihei", - "LocationState": "Hawaii", - "LocationZip": "96753", - "LocationCountry": "United States", - } - ], - }, - "IPDSharingStatementModule": { - "IPDSharing": "Yes", - "IPDSharingDescription": "description of the IPD sharing statement", - "IPDSharingInfoTypeList": [ - "Study Protocol", - "Statistical Analysis Plan (SAP)", - ], - "IPDSharingTimeFrame": "Beginning 9 Months and ending 36 months ", - "IPDSharingAccessCriteria": "This is the IPD sharing access criteria", - "IPDSharingURL": "https://example.com", + "eligibilityModule": { + "sex": "All", + "genderBased": "No", + "minimumAge": "18 Years", + "maximumAge": "65 Years", + "healthyVolunteers": "No", + "eligibilityCriteria": { + "eligibilityCriteriaInclusion": ["crietia 1", "crietia 2"], + "eligibilityCriteriaExclusion": ["crietia 1", "crietia 2"], + }, }, - "ReferencesModule": { - "ReferenceList": [ + "contactsLocationsModule": { + "centralContactList": [ { - "ReferenceID": "12345678", - "ReferenceType": "Yes", - "ReferenceCitation": "This is a reference citation", + "centralContactFirstName": "Ethan", + "centralContactLastName": "Spiller", + "centralContactAffiliation": { + "centralContactAffiliationName": "White Lotus", + }, + "centralContactPhone": "805-555-5555", + "centralContactPhoneExt": "123", + "centralContactEMail": "e.spiller@hbo.com", } ], - "SeeAlsoLinkList": [ + "overallOfficialList": [ { - "SeeAlsoLinkLabel": "This is a link label", - "SeeAlsoLinkURL": "https://example.com", + "overallOfficialFirstName": "Daphne", + "overallOfficialLastName": "Sullivan", + "overallOfficialAffiliation": { + "overallOfficialAffiliationName": "White Lotus", + }, + "overallOfficialRole": "Study Principal Investigator", } ], - "AvailIPDList": [ + "locationList": [ { - "AvailIPDId": "123456", - "AvailIPDType": "Clinical Study Report", - "AvailIPDURL": "https://example.com", - "AvailIPDComment": "This is the avail IPD access criteria", + "locationFacility": "White Lotus", + "locationStatus": "Recruiting", + "locationCity": "Kihei", + "locationState": "Hawaii", + "locationZip": "96753", + "locationCountry": "United States", } ], }, @@ -672,3 +633,20 @@ def test_valid_license_with_identifier(self, tmp_path): ) assert path.exists(file) is True + + +class TestGenerateDatatypeDescription: + def test_valid_datatype_description(self, tmp_path): + data = [ + "ecg", + "eye_fundus_photography_data", + "flio_data", + "phyisical_activity_monitoring_data", + ] + + file = tmp_path / "datatype_description.yaml" + file_type = "yaml" + + generate_datatype_file(data=data, file_path=file, file_type=file_type) + + assert path.exists(file) is True diff --git a/tests/test_utils.py b/tests/test_utils.py index 9aac9ea..27c38e4 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,11 +1,19 @@ """Sample unit test module using pytest-describe and expecter.""" + # pylint: disable=redefined-outer-name,unused-variable,expression-not-assigned,singleton-comparison # noqa: E501 # import os import pytest +from copy import deepcopy +from typing import Any, Dict -from pyfairdatatools.utils import feet_to_meters, requestJSON, validate_file_path +from pyfairdatatools.utils import ( + feet_to_meters, + requestJSON, + validate_file_path, + convert_for_datacite, +) class TestDescribeFeetToMeters: @@ -41,3 +49,215 @@ def test_when_invalid_path(self): # root_file_path = os.path.join(os.path.abspath(os.sep), "README.md") # print(root_file_path) # validate_file_path(root_file_path, writable=True) + + +class TestConvertToDatacite: + """Test the convert_to_datacite function.""" + + valid_data: Dict[str, Any] = { + "identifier": { + "identifierValue": "10.5281/zenodo.1234567", + "identifierType": "DOI", + }, + "title": [ + { + "titleValue": "Main Title", + }, + { + "titleValue": "Subtitle", + "titleType": "Subtitle", + }, + ], + "version": "1.0.0", + "alternateIdentifier": [ + { + "alternateIdentifierValue": "10.5281/zenodo.1234567", + "alternateIdentifierType": "DOI", + } + ], + "creator": [ + { + "creatorName": "Doe, John", + "nameType": "Personal", + "nameIdentifier": [ + { + "nameIdentifierValue": "0000-0001-2345-6789", + "nameIdentifierScheme": "ORCID", + "schemeURI": "https://orcid.org", + } + ], + "affiliation": [ + { + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, + } + ], + }, + { + "creatorName": "White Lotus Research", + "nameType": "Organizational", + "nameIdentifier": [ + { + "nameIdentifierValue": "0000-0001-2345-6789", + "nameIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + } + ], + }, + ], + "contributor": [ + { + "contributorType": "ContactPerson", + "contributorName": "Doe, John", + "nameType": "Personal", + "nameIdentifier": [ + { + "nameIdentifierValue": "0000-0001-2345-6789", + "nameIdentifierScheme": "ORCID", + "schemeURI": "https://orcid.org", + } + ], + "affiliation": [ + { + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, + } + ], + }, + { + "contributorType": "HostingInstitution", + "contributorName": "White Lotus Research", + "nameType": "Organizational", + "nameIdentifier": [ + { + "nameIdentifierValue": "0000-0001-2345-6789", + "nameIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + } + ], + }, + ], + "publicationYear": "2023", + "date": [ + { + "dateValue": "2023-01-01", + "dateType": "Collected", + "dateInformation": "Some information", + } + ], + "resourceType": { + "resourceTypeValue": "Diabetes", + "resourceTypeGeneral": "Dataset", + }, + "datasetDeIdentLevel": { + "deIdentType": "NoDeIdentification", + "deIdentDirect": True, + "deIdentHIPAA": True, + "deIdentDates": True, + "deIdentNonarr": True, + "deIdentKAnon": True, + "deIdentDetails": "Some details", + }, + "datasetConsent": { + "consentType": "NoRestriction", + "consentNoncommercial": True, + "consentGeogRestrict": True, + "consentResearchType": True, + "consentGeneticOnly": True, + "consentNoMethods": True, + "consentsDetails": "Some details", + }, + "description": [ + {"descriptionValue": "Some description", "descriptionType": "Abstract"}, + {"descriptionValue": "Some description", "descriptionType": "Methods"}, + ], + "language": "en", + "relatedIdentifier": [ + { + "relatedIdentifierValue": "10.5281/zenodo.1234567", + "relatedIdentifierType": "DOI", + "relationType": "IsCitedBy", + "relatedMetadataScheme": "DataCite", + "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", # noqa: E501 pylint: disable=line-too-long + "schemeType": "DOI", + "resourceTypeGeneral": "Dataset", + } + ], + "subject": [ + { + "subjectValue": "Diabetes", + "subjectIdentifier": { + "classificationCode": "E11.9", + "subjectScheme": "MeSH", + "schemeURI": "https://www.nlm.nih.gov/mesh/", + "valueURI": "https://www.nlm.nih.gov/mesh/1234567", + }, + } + ], + "managingOrganization": { + "name": "Test Organization", + "managingOrganizationIdentifier": { + "managingOrganizationIdentifierValue": "04z8jg394", + "managingOrganizationScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, + }, + "accessType": "PublicOnScreenAccess", + "accessDetails": { + "description": "Some description", + "url": "https://example.com", + "urlLastChecked": "2021-01-01", + }, + "rights": [ + { + "rightsName": "CC0-1.0", + "rightsURI": "https://creativecommons.org/publicdomain/zero/1.0/", + "rightsIdentifier": { + "rightsIdentifierValue": "CC0-1.0", + "rightsIdentifierScheme": "SPDX", + "schemeURI": "https://spdx.org/licenses/", + }, + } + ], + "publisher": { + "publisherName": "Test Publisher", + "publisherIdentifier": { + "publisherIdentifierValue": "04z8jg394", + "publisherIdentifierScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, + }, + "size": ["15 pages", "15 MB"], + "format": ["application/pdf", "text/xml", "MOPG", "nifti"], + "fundingReference": [ + { + "funderName": "Test Funder", + "funderIdentifier": { + "funderIdentifierValue": "1234567", + "funderIdentifierType": "Crossref Funder ID", + "schemeURI": "https://doi.org/10.13039/501100001711", + }, + "awardNumber": { + "awardNumberValue": "1234567", + "awardURI": "https://doi.org/10.13039/501100001711", + }, + "awardTitle": "Test Award", + } + ], + } + + def test_when_valid_data(self): + """Test when valid data is provided.""" + data = deepcopy(self.valid_data) + + output = convert_for_datacite(data) + + assert output is not None diff --git a/tests/test_validate.py b/tests/test_validate.py index a0fb8e6..ab5c205 100644 --- a/tests/test_validate.py +++ b/tests/test_validate.py @@ -1,10 +1,12 @@ """Unit tests for pyfairdatatools.validate module.""" + # pylint: disable=too-many-lines from copy import deepcopy from typing import Any, Dict from pyfairdatatools.validate import ( validate_dataset_description, + validate_datatype_dictionary, validate_license, validate_participants, validate_readme, @@ -13,12 +15,15 @@ class TestValidateDatasetDescription: + """Unit tests for validate_dataset_description function.""" + valid_data: Dict[str, Any] = { - "Identifier": { + "schema": "https://schema.aireadi.org/v0.1.0/dataset_description.json", + "identifier": { "identifierValue": "10.5281/zenodo.1234567", "identifierType": "DOI", }, - "Title": [ + "title": [ { "titleValue": "Main Title", }, @@ -27,14 +32,14 @@ class TestValidateDatasetDescription: "titleType": "Subtitle", }, ], - "Version": "1.0.0", - "AlternateIdentifier": [ + "version": "1.0.0", + "alternateIdentifier": [ { "alternateIdentifierValue": "10.5281/zenodo.1234567", "alternateIdentifierType": "DOI", } ], - "Creator": [ + "creator": [ { "creatorName": "Doe, John", "nameType": "Personal", @@ -47,10 +52,12 @@ class TestValidateDatasetDescription: ], "affiliation": [ { - "affiliationValue": "White Lotus", - "affiliationIdentifier": "https://ror.org/123456789", - "affiliationIdentifierScheme": "ROR", - "schemeURI": "https://ror.org", + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, } ], }, @@ -66,7 +73,7 @@ class TestValidateDatasetDescription: ], }, ], - "Contributor": [ + "contributor": [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -80,10 +87,12 @@ class TestValidateDatasetDescription: ], "affiliation": [ { - "affiliationValue": "White Lotus", - "affiliationIdentifier": "https://ror.org/123456789", - "affiliationIdentifierScheme": "ROR", - "schemeURI": "https://ror.org", + "affiliationName": "White Lotus", + "affiliationIdentifier": { + "affiliationIdentifierValue": "https://ror.org/123456789", + "affiliationIdentifierScheme": "ROR", + "schemeURI": "https://ror.org", + }, } ], }, @@ -100,20 +109,19 @@ class TestValidateDatasetDescription: ], }, ], - "PublicationYear": "2023", - "Date": [ + "publicationYear": "2023", + "date": [ { "dateValue": "2023-01-01", "dateType": "Collected", "dateInformation": "Some information", } ], - "ResourceType": { + "resourceType": { "resourceTypeValue": "Diabetes", "resourceTypeGeneral": "Dataset", }, - "DatasetRecordKeys": {"keysType": "Anonymised", "keysDetails": "Some details"}, - "DatasetDeIdentLevel": { + "datasetDeIdentLevel": { "deIdentType": "NoDeIdentification", "deIdentDirect": True, "deIdentHIPAA": True, @@ -122,7 +130,7 @@ class TestValidateDatasetDescription: "deIdentKAnon": True, "deIdentDetails": "Some details", }, - "DatasetConsent": { + "datasetConsent": { "consentType": "NoRestriction", "consentNoncommercial": True, "consentGeogRestrict": True, @@ -131,52 +139,69 @@ class TestValidateDatasetDescription: "consentNoMethods": True, "consentsDetails": "Some details", }, - "Description": [ + "description": [ {"descriptionValue": "Some description", "descriptionType": "Abstract"}, {"descriptionValue": "Some description", "descriptionType": "Methods"}, ], - "Language": "en", - "RelatedIdentifier": [ + "language": "en", + "relatedIdentifier": [ { "relatedIdentifierValue": "10.5281/zenodo.1234567", "relatedIdentifierType": "DOI", - "relationType": "HasMetadata", + "relationType": "IsCitedBy", "relatedMetadataScheme": "DataCite", - "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", + "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", # noqa: E501 pylint: disable=line-too-long "schemeType": "DOI", "resourceTypeGeneral": "Dataset", } ], - "Subject": [ + "subject": [ { "subjectValue": "Diabetes", - "subjectScheme": "MeSH", - "schemeURI": "https://www.nlm.nih.gov/mesh/", - "valueURI": "https://www.nlm.nih.gov/mesh/1234567", - "classificationCode": "E11.9", + "subjectIdentifier": { + "classificationCode": "E11.9", + "subjectScheme": "MeSH", + "schemeURI": "https://www.nlm.nih.gov/mesh/", + "valueURI": "https://www.nlm.nih.gov/mesh/1234567", + }, } ], - "ManagingOrganisation": { - "name": "Test Organisation", - "rorId": "https://ror.org/123456789", + "managingOrganization": { + "name": "Test Organization", + "managingOrganizationIdentifier": { + "managingOrganizationIdentifierValue": "04z8jg394", + "managingOrganizationScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, }, - "AccessType": "PublicOnScreenAccess", - "AccessDetails": { + "accessType": "PublicOnScreenAccess", + "accessDetails": { "description": "Some description", "url": "https://example.com", "urlLastChecked": "2021-01-01", }, - "Rights": [ + "rights": [ { - "rightsValue": "CC0-1.0", + "rightsName": "CC0-1.0", "rightsURI": "https://creativecommons.org/publicdomain/zero/1.0/", - "rightsIdentifier": "CC0-1.0", - "rightsIdentifierScheme": "SPDX", + "rightsIdentifier": { + "rightsIdentifierValue": "CC0-1.0", + "rightsIdentifierScheme": "SPDX", + "schemeURI": "https://spdx.org/licenses/", + }, } ], - "Publisher": "GitHub", - "Size": ["15 pages", "15 MB"], - "FundingReference": [ + "publisher": { + "publisherName": "Test Publisher", + "publisherIdentifier": { + "publisherIdentifierValue": "04z8jg394", + "publisherIdentifierScheme": "ROR", + "schemeURI": "https://www.crossref.org/", + }, + }, + "size": ["15 pages", "15 MB"], + "format": ["application/pdf", "text/xml", "MOPG", "nifti"], + "fundingReference": [ { "funderName": "Test Funder", "funderIdentifier": { @@ -191,64 +216,13 @@ class TestValidateDatasetDescription: "awardTitle": "Test Award", } ], - "RelatedItem": [ - { - "relatedItemType": "Book", - "relationType": "IsMetadataFor", - "relatedItemIdentifier": [ - { - "relatedItemIdentifierValue": "10.5281/zenodo.1234567", - "relatedItemIdentifierType": "DOI", - "relatedMetadataScheme": "DataCite", - "schemeURI": "https://schema.datacite.org/meta/kernel-4.3/doc/DataCite-MetadataKernel_v4.3.pdf", - "schemeType": "DDT", - } - ], - "creator": [ - { - "creatorName": "Doe, John", - "nameType": "Personal", - } - ], - "title": [ - { - "titleValue": "Test title", - } - ], - "publicationYear": "2021", - "volume": "1", - "issue": "1", - "number": {"numberValue": "1", "numberType": "Article"}, - "firstPage": "1", - "lastPage": "15", - "publisher": "Test Publisher", - "edition": "1", - "contributor": [ - { - "contributorType": "Editor", - "contributorName": "Doe, John", - "nameType": "Personal", - } - ], - } - ], } - def test_valid_dataset_description(self): - data = deepcopy(self.valid_data) - - try: - output = validate_dataset_description(data) - except Exception as e: - print(e) - output = False - - assert output is True - def test_identifier(self): + """Test identifier validation.""" data = deepcopy(self.valid_data) - data["Identifier"] = { + data["identifier"] = { "identifierValue": "", } @@ -257,7 +231,7 @@ def test_identifier(self): data = deepcopy(self.valid_data) - data["Identifier"] = { + data["identifier"] = { "identifierValue": "invalid", } @@ -265,23 +239,24 @@ def test_identifier(self): assert output is False def test_title(self): + """Test title validation.""" data = deepcopy(self.valid_data) - data["Title"] = [] + data["title"] = [] output = validate_dataset_description(data) assert output is False data = deepcopy(self.valid_data) - data["Title"] = [{"titleValue": "Test", "titleType": ""}] + data["title"] = [{"titleValue": "Test", "titleType": ""}] output = validate_dataset_description(data) assert output is False data = deepcopy(self.valid_data) - data["Title"] = [ + data["title"] = [ {"titleValue": "Test"}, {"titleValue": "Test", "titleType": "Invalid"}, ] @@ -290,17 +265,19 @@ def test_title(self): assert output is False def test_version(self): + """Test version validation.""" data = deepcopy(self.valid_data) - data["Version"] = "" + data["version"] = "" output = validate_dataset_description(data) assert output is False def test_alternate_identifier(self): + """Test alternate identifier validation.""" data = deepcopy(self.valid_data) - data["AlternateIdentifier"] = [ + data["alternateIdentifier"] = [ {"alternateIdentifierValue": "", "alternateIdentifierType": "DOI"} ] @@ -309,7 +286,7 @@ def test_alternate_identifier(self): data = deepcopy(self.valid_data) - data["AlternateIdentifier"] = [ + data["alternateIdentifier"] = [ { "alternateIdentifierValue": "10.5281/zenodo.7942786", } @@ -320,7 +297,7 @@ def test_alternate_identifier(self): data = deepcopy(self.valid_data) - data["AlternateIdentifier"] = [ + data["alternateIdentifier"] = [ { "alternateIdentifierValue": "10.5281/zenodo.7942786", "alternateIdentifierType": "Invalid", @@ -331,16 +308,17 @@ def test_alternate_identifier(self): assert output is False def test_creator(self): + """Test creator validation.""" data = deepcopy(self.valid_data) - data["Creator"] = [] + data["creator"] = [] output = validate_dataset_description(data) assert output is False data = deepcopy(self.valid_data) - data["Creator"] = [ + data["creator"] = [ { "creatorName": "Doe, John", } @@ -351,7 +329,7 @@ def test_creator(self): data = deepcopy(self.valid_data) - data["Creator"] = [ + data["creator"] = [ { "creatorName": "Doe, John", "nameType": "Invalid", @@ -363,7 +341,7 @@ def test_creator(self): data = deepcopy(self.valid_data) - data["Creator"] = [ + data["creator"] = [ { "creatorName": "Doe, John", "nameType": "Invalid", @@ -376,7 +354,7 @@ def test_creator(self): data = deepcopy(self.valid_data) - data["Creator"] = [ + data["creator"] = [ { "creatorName": "Doe, John", "nameType": "Invalid", @@ -392,7 +370,7 @@ def test_creator(self): data = deepcopy(self.valid_data) - data["Creator"] = [ + data["creator"] = [ { "creatorName": "Doe, John", "nameType": "Invalid", @@ -408,9 +386,10 @@ def test_creator(self): assert output is False def test_contributor(self): + """Test contributor validation.""" data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "invalid", "contributorName": "Doe, John", @@ -423,7 +402,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -436,7 +415,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -450,7 +429,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -468,7 +447,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -488,7 +467,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -502,7 +481,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -519,7 +498,7 @@ def test_contributor(self): data = deepcopy(self.valid_data) - data["Contributor"] = [ + data["contributor"] = [ { "contributorType": "ContactPerson", "contributorName": "Doe, John", @@ -535,25 +514,65 @@ def test_contributor(self): output = validate_dataset_description(data) assert output is False + def test_related_identifier(self): + """Test related identifier validation.""" + data = deepcopy(self.valid_data) + + data["relatedIdentifier"] = [ + { + "relatedIdentifierValue": "", + "relatedIdentifierType": "DOI", + "relationType": "HasMetadata", + } + ] + + output = validate_dataset_description(data) + assert output is False + + data = deepcopy(self.valid_data) + + data["relatedIdentifier"] = [ + { + "relatedIdentifierValue": "10.5281/zenodo.7942786", + } + ] + + output = validate_dataset_description(data) + assert output is False + + data = deepcopy(self.valid_data) + + data["relatedIdentifier"] = [ + { + "relatedIdentifierValue": "10.5281/zenodo.7942786", + "relatedIdentifierType": "Invalid", + } + ] + + output = validate_dataset_description(data) + assert output is False + def test_publication_year(self): + """Test publication year validation.""" data = deepcopy(self.valid_data) - data["PublicationYear"] = "98" + data["publicationYear"] = "98" output = validate_dataset_description(data) assert output is False def test_date(self): + """Test date validation.""" data = deepcopy(self.valid_data) - data["Date"] = [] + data["date"] = [] output = validate_dataset_description(data) assert output is False data = deepcopy(self.valid_data) - data["Date"] = [ + data["date"] = [ {"dateValue": "2004-03-02", "dateType": "invalid", "dateInformation": ""} ] @@ -561,351 +580,364 @@ def test_date(self): assert output is False def test_language(self): + """Test language validation.""" data = deepcopy(self.valid_data) - data["Language"] = "en-US" + data["language"] = "en-US" output = validate_dataset_description(data) assert output is True data = deepcopy(self.valid_data) - data["Language"] = "" + data["language"] = "" + + output = validate_dataset_description(data) + assert output is False + + data = deepcopy(self.valid_data) + + data["language"] = ["invalid"] output = validate_dataset_description(data) assert output is False + def test_resource_type(self): + """Test valid resource type.""" data = deepcopy(self.valid_data) - data["Language"] = ["invalid"] + data["resourceType"] = { + "resourceTypeValue": "Diabetes", + "resourceTypeGeneral": "Invalid", + } output = validate_dataset_description(data) assert output is False + data = deepcopy(self.valid_data) + + output = validate_dataset_description(data) + assert output is True + + def test_valid_dataset_description(self): + """Test valid dataset description.""" + data = deepcopy(self.valid_data) + + try: + output = validate_dataset_description(data) + except Exception as e: # pylint: disable=broad-except + print(e) + output = False + + assert output + class TestValidateStudyDescription: + """Unit tests for validate_study_description function.""" + observational_study_valid_data: Dict[str, Any] = { - "IdentificationModule": { - "OrgStudyIdInfo": { - "OrgStudyId": "RandomStudyId", - "OrgStudyIdType": "Registry Identifier", - "OrgStudyIdDomain": "ClinicalTrials.gov", - "OrgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", + "schema": "https://schema.aireadi.org/v0.1.0/study_description.json", + "identificationModule": { + "officialTitle": "Test Title", + "acronym": "TT", + "orgStudyIdInfo": { + "orgStudyId": "RandomStudyId", + "orgStudyIdType": "Registry Identifier", + "orgStudyIdDomain": "ClinicalTrials.gov", + "orgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", }, - "SecondaryIdInfoList": [ + "secondaryIdInfoList": [ { - "SecondaryId": "SomeID", - "SecondaryIdType": "Other Identifier", - "SecondaryIdDomain": "Other", - "SecondaryIdLink": "https://example.com", + "secondaryId": "SomeID", + "secondaryIdType": "Other Identifier", + "secondaryIdDomain": "Other", + "secondaryIdLink": "https://example.com", } ], }, - "StatusModule": { - "OverallStatus": "Suspended", - "WhyStopped": "Study stopped due to lack of funding", - "StartDateStruct": { - "StartDate": "July 07, 2023", - "StartDateType": "Actual", + "statusModule": { + "overallStatus": "Suspended", + "whyStopped": "Study stopped due to lack of funding", + "startDateStruct": { + "startDate": "2023-06", + "startDateType": "Actual", }, - "CompletionDateStruct": { - "CompletionDate": "July 08, 2024", - "CompletionDateType": "Actual", + "completionDateStruct": { + "completionDate": "2024-06", + "completionDateType": "Actual", }, }, - "SponsorCollaboratorsModule": { - "ResponsibleParty": { - "ResponsiblePartyType": "Principal Investigator", - "ResponsiblePartyInvestigatorFullName": "Harper Spiller", - "ResponsiblePartyInvestigatorTitle": "Principal Investigator", - "ResponsiblePartyInvestigatorAffiliation": "White Lotus", + "sponsorCollaboratorsModule": { + "responsibleParty": { + "responsiblePartyType": "Principal Investigator", + "responsiblePartyInvestigatorFirstName": "Harper", + "responsiblePartyInvestigatorLastName": "Spiller", + "responsiblePartyInvestigatorTitle": "Principal Investigator", + "responsiblePartyInvestigatorAffiliation": { + "responsiblePartyInvestigatorAffiliationName": "White Lotus", + }, }, - "LeadSponsor": {"LeadSponsorName": "Harper Spiller"}, - "CollaboratorList": [ - {"CollaboratorName": "Nicole Mossbacher"}, - {"CollaboratorName": "Olivia Mossbacher"}, + "leadSponsor": {"leadSponsorName": "Harper Spiller"}, + "collaboratorList": [ + {"collaboratorName": "Nicole Mossbacher"}, + {"collaboratorName": "Olivia Mossbacher"}, ], }, - "OversightModule": { - "OversightHasDMC": "No", + "oversightModule": { + "isFDARegulatedDrug": "No", + "isFDARegulatedDevice": "No", + "humanSubjectReviewStatus": "Request not yet submitted", + "oversightHasDMC": "No", }, - "DescriptionModule": { - "BriefSummary": "This is a brief summary", - "DetailedDescription": "This is a detailed description", + "descriptionModule": { + "briefSummary": "This is a brief summary", + "detailedDescription": "This is a detailed description", }, - "ConditionsModule": { - "ConditionList": ["Condition 1", "Condition 2"], - "KeywordList": ["Keyword 1", "Keyword 2"], + "conditionsModule": { + "conditionList": [ + {"conditionName": "Condition 1"}, + {"conditionName": "Condition 2"}, + ], + "keywordList": [ + {"keywordValue": "Keyword 1"}, + {"keywordValue": "Keyword 2"}, + ], }, - "DesignModule": { - "StudyType": "Observational", - "DesignInfo": { - "DesignObservationalModelList": ["Cohort"], - "DesignTimePerspectiveList": ["Prospective"], + "designModule": { + "studyType": "Observational", + "designInfo": { + "designObservationalModelList": ["Cohort"], + "designTimePerspectiveList": ["Prospective"], }, - "BioSpec": { - "BioSpecRetention": "Samples With DNA", - "BioSpecDescription": "This is a description of the biospecs", + "bioSpec": { + "bioSpecRetention": "Samples With DNA", + "bioSpecDescription": "This is a description of the biospecs", }, - "EnrollmentInfo": { - "EnrollmentCount": "34", - "EnrollmentType": "Anticipated", + "enrollmentInfo": { + "enrollmentCount": "34", + "enrollmentType": "Anticipated", }, - "TargetDuration": "4 Years", - "NumberGroupsCohorts": "1", + "targetDuration": "4 Years", + "numberGroupsCohorts": "1", + "isPatientRegistry": "Yes", }, - "ArmsInterventionsModule": { - "ArmGroupList": [ - {"ArmGroupLabel": "Arm 1", "ArmGroupDescription": "Experimental"} + "armsInterventionsModule": { + "armGroupList": [ + {"armGroupLabel": "Arm 1", "armGroupDescription": "Experimental"} ], - "InterventionList": [ + "interventionList": [ { - "InterventionType": "Drug", - "InterventionName": "Drug 1", - "InterventionDescription": "description of the intervention", - "InterventionArmGroupLabelList": ["Arm 1"], - "InterventionOtherNameList": ["Other Name 1"], + "interventionType": "Drug", + "interventionName": "Drug 1", + "interventionDescription": "description of the intervention", + "interventionOtherNameList": ["Other Name 1"], }, ], }, - "EligibilityModule": { - "Gender": "All", - "GenderBased": "No", - "MinimumAge": "18 Years", - "MaximumAge": "65 Years", - "EligibilityCriteria": "This is the eligibility criteria", - "StudyPopulation": "This is the study population", - "SamplingMethod": "Non-Probability Sample", - }, - "ContactsLocationsModule": { - "CentralContactList": [ - { - "CentralContactName": "Ethan Spiller", - "CentralContactAffiliation": "White Lotus", - "CentralContactPhone": "805-555-5555", - "CentralContactPhoneExt": "123", - "CentralContactEMail": "e.spiller@hbo.com", - } - ], - "OverallOfficialList": [ - { - "OverallOfficialName": "Daphne Sullivan", - "OverallOfficialAffiliation": "White Lotus", - "OverallOfficialRole": "Study Principal Investigator", - } - ], - "LocationList": [ - { - "LocationFacility": "White Lotus", - "LocationStatus": "Recruiting", - "LocationCity": "Kihei", - "LocationState": "Hawaii", - "LocationZip": "96753", - "LocationCountry": "United States", - } - ], - }, - "IPDSharingStatementModule": { - "IPDSharing": "Yes", - "IPDSharingDescription": "description of the IPD sharing statement", - "IPDSharingInfoTypeList": [ - "Study Protocol", - "Statistical Analysis Plan (SAP)", - ], - "IPDSharingTimeFrame": "Beginning 9 Months and ending 36 months", - "IPDSharingAccessCriteria": "This is the IPD sharing access criteria", - "IPDSharingURL": "https://example.com", + "eligibilityModule": { + "sex": "All", + "genderBased": "No", + "minimumAge": "18 Years", + "maximumAge": "65 Years", + "eligibilityCriteria": { + "eligibilityCriteriaInclusion": ["crietia 1", "crietia 2"], + "eligibilityCriteriaExclusion": ["crietia 1", "crietia 2"], + }, + "studyPopulation": "This is the study population", + "healthyVolunteers": "No", + "samplingMethod": "Non-Probability Sample", }, - "ReferencesModule": { - "ReferenceList": [ + "contactsLocationsModule": { + "centralContactList": [ { - "ReferenceID": "12345678", - "ReferenceType": "Yes", - "ReferenceCitation": "This is a reference citation", + "centralContactFirstName": "Ethan", + "centralContactLastName": "Spiller", + "centralContactAffiliation": { + "centralContactAffiliationName": "White Lotus", + }, + "centralContactPhone": "805-555-5555", + "centralContactPhoneExt": "123", + "centralContactEMail": "e.spiller@hbo.com", } ], - "SeeAlsoLinkList": [ + "overallOfficialList": [ { - "SeeAlsoLinkLabel": "This is a link label", - "SeeAlsoLinkURL": "https://example.com", + "overallOfficialFirstName": "Daphne", + "overallOfficialLastName": "Sullivan", + "overallOfficialAffiliation": { + "overallOfficialAffiliationName": "White Lotus", + }, + "overallOfficialRole": "Study Principal Investigator", } ], - "AvailIPDList": [ + "locationList": [ { - "AvailIPDId": "123456", - "AvailIPDType": "Clinical Study Report", - "AvailIPDURL": "https://example.com", - "AvailIPDComment": "This is the avail IPD access criteria", + "locationFacility": "White Lotus", + "locationStatus": "Recruiting", + "locationCity": "Kihei", + "locationState": "Hawaii", + "locationZip": "96753", + "locationCountry": "United States", } ], }, } interventional_study_valid_data: Dict[str, Any] = { - "IdentificationModule": { - "OrgStudyIdInfo": { - "OrgStudyId": "RandomStudyId", - "OrgStudyIdType": "Registry Identifier", - "OrgStudyIdDomain": "ClinicalTrials.gov", - "OrgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", + "schema": "https://schema.aireadi.org/v0.1.0/study_description.json", + "identificationModule": { + "officialTitle": "Test Title", + "acronym": "TT", + "orgStudyIdInfo": { + "orgStudyId": "RandomStudyId", + "orgStudyIdType": "Registry Identifier", + "orgStudyIdDomain": "ClinicalTrials.gov", + "orgStudyIdLink": "https://clinicaltrials.gov/ct2/show/NCT00000000", }, - "SecondaryIdInfoList": [ + "secondaryIdInfoList": [ { - "SecondaryId": "SomeID", - "SecondaryIdType": "Other Identifier", - "SecondaryIdDomain": "Other", - "SecondaryIdLink": "https://example.com", + "secondaryId": "SomeID", + "secondaryIdType": "Other Identifier", + "secondaryIdDomain": "Other", + "secondaryIdLink": "https://example.com", } ], }, - "StatusModule": { - "OverallStatus": "Suspended", - "WhyStopped": "Study stopped due to lack of funding", - "StartDateStruct": { - "StartDate": "July 07, 2023", - "StartDateType": "Actual", + "statusModule": { + "overallStatus": "Suspended", + "whyStopped": "Study stopped due to lack of funding", + "startDateStruct": { + "startDate": "2023-06", + "startDateType": "Actual", }, - "CompletionDateStruct": { - "CompletionDate": "July 08, 2024", - "CompletionDateType": "Actual", + "completionDateStruct": { + "completionDate": "2024-06", + "completionDateType": "Actual", }, }, - "SponsorCollaboratorsModule": { - "ResponsibleParty": { - "ResponsiblePartyType": "Principal Investigator", - "ResponsiblePartyInvestigatorFullName": "Harper Spiller", - "ResponsiblePartyInvestigatorTitle": "Principal Investigator", - "ResponsiblePartyInvestigatorAffiliation": "White Lotus", + "sponsorCollaboratorsModule": { + "responsibleParty": { + "responsiblePartyType": "Principal Investigator", + "responsiblePartyInvestigatorFirstName": "Harper", + "responsiblePartyInvestigatorLastName": "Spiller", + "responsiblePartyInvestigatorTitle": "Principal Investigator", + "responsiblePartyInvestigatorAffiliation": { + "responsiblePartyInvestigatorAffiliationName": "White Lotus", + }, }, - "LeadSponsor": {"LeadSponsorName": "Harper Spiller"}, - "CollaboratorList": [ - {"CollaboratorName": "Nicole Mossbacher"}, - {"CollaboratorName": "Olivia Mossbacher"}, + "leadSponsor": {"leadSponsorName": "Harper Spiller"}, + "collaboratorList": [ + {"collaboratorName": "Nicole Mossbacher"}, + {"collaboratorName": "Olivia Mossbacher"}, ], }, - "OversightModule": { - "OversightHasDMC": "No", + "oversightModule": { + "isFDARegulatedDrug": "No", + "isFDARegulatedDevice": "No", + "humanSubjectReviewStatus": "Request not yet submitted", + "oversightHasDMC": "No", }, - "DescriptionModule": { - "BriefSummary": "This is a brief summary", - "DetailedDescription": "This is a detailed description", + "descriptionModule": { + "briefSummary": "This is a brief summary", + "detailedDescription": "This is a detailed description", }, - "ConditionsModule": { - "ConditionList": ["Condition 1", "Condition 2"], - "KeywordList": ["Keyword 1", "Keyword 2"], + "conditionsModule": { + "conditionList": [ + {"conditionName": "Condition 1"}, + {"conditionName": "Condition 2"}, + ], + "keywordList": [ + {"keywordValue": "Keyword 1"}, + {"keywordValue": "Keyword 2"}, + ], }, - "DesignModule": { - "StudyType": "Interventional", - "DesignInfo": { - "DesignAllocation": "Randomized", - "DesignInterventionModel": "Prevention", - "DesignInterventionModelDescription": "description", - "DesignPrimaryPurpose": "Parallel Assignment", - "DesignMaskingInfo": { - "DesignMasking": "Blinded (no details)", - "DesignMaskingDescription": "description of the design masking", - "DesignWhoMaskedList": ["Participant", "Care Provider"], + "designModule": { + "studyType": "Interventional", + "designInfo": { + "designAllocation": "Randomized", + "designInterventionModel": "Prevention", + "designInterventionModelDescription": "description", + "designPrimaryPurpose": "Parallel Assignment", + "designMaskingInfo": { + "designMasking": "Blinded (no details)", + "designMaskingDescription": "description of the design masking", + "designWhoMaskedList": ["Participant", "Care Provider"], }, }, - "PhaseList": ["Phase 1/2"], - "EnrollmentInfo": { - "EnrollmentCount": "34", - "EnrollmentType": "Anticipated", + "phaseList": ["Phase 1/2"], + "enrollmentInfo": { + "enrollmentCount": "34", + "enrollmentType": "Anticipated", }, - "NumberArms": "1", + "numberArms": "1", }, - "ArmsInterventionsModule": { - "ArmGroupList": [ + "armsInterventionsModule": { + "armGroupList": [ { - "ArmGroupLabel": "Arm 1", - "ArmGroupType": "Placebo Comparator", - "ArmGroupDescription": "Experimental", - "ArmGroupInterventionList": ["Drug 1"], + "armGroupLabel": "Arm 1", + "armGroupType": "Placebo Comparator", + "armGroupDescription": "Experimental", + "armGroupInterventionList": ["Drug 1"], } ], - "InterventionList": [ + "interventionList": [ { - "InterventionType": "Drug", - "InterventionName": "Drug 1", - "InterventionDescription": "description of the intervention", - "InterventionArmGroupLabelList": ["Arm 1"], - "InterventionOtherNameList": ["Other Name 1"], + "interventionType": "Drug", + "interventionName": "Drug 1", + "interventionDescription": "description of the intervention", + "interventionOtherNameList": ["Other Name 1"], }, ], }, - "EligibilityModule": { - "Gender": "All", - "GenderBased": "No", - "MinimumAge": "18 Years", - "MaximumAge": "65 Years", - "HealthyVolunteers": "No", - "EligibilityCriteria": "This is the eligibility criteria", - }, - "ContactsLocationsModule": { - "CentralContactList": [ - { - "CentralContactName": "Ethan Spiller", - "CentralContactAffiliation": "White Lotus", - "CentralContactPhone": "805-555-5555", - "CentralContactPhoneExt": "123", - "CentralContactEMail": "e.spiller@hbo.com", - } - ], - "OverallOfficialList": [ - { - "OverallOfficialName": "Daphne Sullivan", - "OverallOfficialAffiliation": "White Lotus", - "OverallOfficialRole": "Study Principal Investigator", - } - ], - "LocationList": [ - { - "LocationFacility": "White Lotus", - "LocationStatus": "Recruiting", - "LocationCity": "Kihei", - "LocationState": "Hawaii", - "LocationZip": "96753", - "LocationCountry": "United States", - } - ], - }, - "IPDSharingStatementModule": { - "IPDSharing": "Yes", - "IPDSharingDescription": "description of the IPD sharing statement", - "IPDSharingInfoTypeList": [ - "Study Protocol", - "Statistical Analysis Plan (SAP)", - ], - "IPDSharingTimeFrame": "Beginning 9 Months and ending 36 months ", - "IPDSharingAccessCriteria": "This is the IPD sharing access criteria", - "IPDSharingURL": "https://example.com", + "eligibilityModule": { + "sex": "All", + "genderBased": "No", + "minimumAge": "18 Years", + "maximumAge": "65 Years", + "healthyVolunteers": "No", + "eligibilityCriteria": { + "eligibilityCriteriaInclusion": ["crietia 1", "crietia 2"], + "eligibilityCriteriaExclusion": ["crietia 1", "crietia 2"], + }, }, - "ReferencesModule": { - "ReferenceList": [ + "contactsLocationsModule": { + "centralContactList": [ { - "ReferenceID": "12345678", - "ReferenceType": "Yes", - "ReferenceCitation": "This is a reference citation", + "centralContactFirstName": "Ethan", + "centralContactLastName": "Spiller", + "centralContactAffiliation": { + "centralContactAffiliationName": "White Lotus", + }, + "centralContactPhone": "805-555-5555", + "centralContactPhoneExt": "123", + "centralContactEMail": "e.spiller@hbo.com", } ], - "SeeAlsoLinkList": [ + "overallOfficialList": [ { - "SeeAlsoLinkLabel": "This is a link label", - "SeeAlsoLinkURL": "https://example.com", + "overallOfficialFirstName": "Daphne", + "overallOfficialLastName": "Sullivan", + "overallOfficialAffiliation": { + "overallOfficialAffiliationName": "White Lotus", + }, + "overallOfficialRole": "Study Principal Investigator", } ], - "AvailIPDList": [ + "locationList": [ { - "AvailIPDId": "123456", - "AvailIPDType": "Clinical Study Report", - "AvailIPDURL": "https://example.com", - "AvailIPDComment": "This is the avail IPD access criteria", + "locationFacility": "White Lotus", + "locationStatus": "Recruiting", + "locationCity": "Kihei", + "locationState": "Hawaii", + "locationZip": "96753", + "locationCountry": "United States", } ], }, } def test_observational_valid_study_description(self): + """Test valid observational study description.""" data = deepcopy(self.observational_study_valid_data) output = validate_study_description(data) @@ -913,20 +945,32 @@ def test_observational_valid_study_description(self): assert output is True def test_interventional_valid_study_description(self): + """Test valid interventional study description.""" data = deepcopy(self.interventional_study_valid_data) output = validate_study_description(data) - assert output is True def test_invalid_identification_module(self): + """Test invalid identification module.""" data = deepcopy(self.observational_study_valid_data) - data["IdentificationModule"]["OrgStudyIdInfo"][ - "OrgStudyIdType" + data["identificationModule"]["orgStudyIdInfo"][ + "orgStudyIdType" ] = "Registry Identifier" - del data["IdentificationModule"]["OrgStudyIdInfo"]["OrgStudyIdDomain"] + del data["identificationModule"]["orgStudyIdInfo"]["orgStudyIdDomain"] + + output = validate_study_description(data) + + assert output is False + + data = deepcopy(self.observational_study_valid_data) + + # sourcery skip: no-loop-in-tests + for item in data["identificationModule"]["secondaryIdInfoList"]: + item["secondaryIdType"] = "Other Identifier" + del item["secondaryIdDomain"] output = validate_study_description(data) @@ -934,34 +978,61 @@ def test_invalid_identification_module(self): data = deepcopy(self.observational_study_valid_data) - for item in data["IdentificationModule"]["SecondaryIdInfoList"]: - item["SecondaryIdType"] = "Other Identifier" - del item["SecondaryIdDomain"] + for item in data["identificationModule"]["secondaryIdInfoList"]: + item["secondaryIdType"] = "Invalid" output = validate_study_description(data) assert output is False def test_invalid_status_module(self): + """Test invalid status module.""" data = deepcopy(self.observational_study_valid_data) - data["StatusModule"]["OverallStatus"] = "Terminated" + data["statusModule"]["overallStatus"] = "Terminated" + + del data["statusModule"]["whyStopped"] + + output = validate_study_description(data) + + assert output is False + + data = deepcopy(self.observational_study_valid_data) - del data["StatusModule"]["WhyStopped"] + data["statusModule"]["overallStatus"] = "Completed" output = validate_study_description(data) + assert output is True + + data = deepcopy(self.observational_study_valid_data) + + data["statusModule"]["overallStatus"] = "Suspended" + + del data["statusModule"]["whyStopped"] + + output = validate_dataset_description(data) + + assert output is False + + data = deepcopy(self.observational_study_valid_data) + + data["statusModule"]["completionDateStruct"]["completionDate"] = "1996" + + output = validate_dataset_description(data) + assert output is False def test_invalid_sponsor_collaborators_module(self): + """Test invalid sponsor collaborators module.""" data = deepcopy(self.observational_study_valid_data) - data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyType" + data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyType" ] = "Sponsor-Investigator" - del data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyInvestigatorFullName" + del data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyInvestigatorFirstName" ] output = validate_study_description(data) @@ -970,12 +1041,12 @@ def test_invalid_sponsor_collaborators_module(self): data = deepcopy(self.observational_study_valid_data) - data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyType" + data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyType" ] = "Sponsor-Investigator" - del data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyInvestigatorTitle" + del data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyInvestigatorTitle" ] output = validate_study_description(data) @@ -984,12 +1055,12 @@ def test_invalid_sponsor_collaborators_module(self): data = deepcopy(self.observational_study_valid_data) - data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyType" + data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyType" ] = "Sponsor-Investigator" - del data["SponsorCollaboratorsModule"]["ResponsibleParty"][ - "ResponsiblePartyInvestigatorAffiliation" + del data["sponsorCollaboratorsModule"]["responsibleParty"][ + "responsiblePartyInvestigatorAffiliation" ] output = validate_study_description(data) @@ -997,19 +1068,21 @@ def test_invalid_sponsor_collaborators_module(self): assert output is False def test_invalid_arms_interventions_module(self): + """Test invalid arms interventions module.""" data = deepcopy(self.interventional_study_valid_data) - for item in data["ArmsInterventionsModule"]["ArmGroupList"]: - del item["ArmGroupType"] + for item in data["armsInterventionsModule"]["armGroupList"]: + del item["armGroupType"] output = validate_study_description(data) assert output is False def test_invalid_eligibilty_module(self): + """Test invalid eligibility module.""" data = deepcopy(self.interventional_study_valid_data) - del data["EligibilityModule"]["HealthyVolunteers"] + del data["eligibilityModule"]["healthyVolunteers"] output = validate_study_description(data) @@ -1017,7 +1090,7 @@ def test_invalid_eligibilty_module(self): data = deepcopy(self.observational_study_valid_data) - del data["EligibilityModule"]["SamplingMethod"] + del data["eligibilityModule"]["samplingMethod"] output = validate_study_description(data) @@ -1025,16 +1098,17 @@ def test_invalid_eligibilty_module(self): data = deepcopy(self.observational_study_valid_data) - del data["EligibilityModule"]["StudyPopulation"] + del data["eligibilityModule"]["studyPopulation"] output = validate_study_description(data) assert output is False def test_invalid_contacts_locations_module(self): + """Test invalid contacts locations module.""" data = deepcopy(self.observational_study_valid_data) - del data["ContactsLocationsModule"]["CentralContactList"] + del data["contactsLocationsModule"]["centralContactList"] output = validate_study_description(data) @@ -1044,6 +1118,8 @@ def test_invalid_contacts_locations_module(self): class TestValidateReadme: + """Unit tests for validate_readme function.""" + def test_minimal_valid_readme(self): data = {"Title": "Test Title"} @@ -1094,7 +1170,10 @@ def test_fail_invalid_publication_date(self): class TestValidateLicense: + """Unit tests for validate_license function.""" + def test_valid_license(self): + """Test valid license.""" data = "CC-BY-4.0" output = validate_license(data) @@ -1102,6 +1181,7 @@ def test_valid_license(self): assert output is True def test_fail_invalid_license(self): + """Test invalid license.""" data = { "License": "Invalid", } @@ -1112,7 +1192,10 @@ def test_fail_invalid_license(self): class TestValidateParticipants: + """Unit tests for validate_participants function.""" + def test_minimal_valid_participant(self): + """Test minimal valid participant.""" data = [ { "participant_id": "sub-user1", @@ -1124,6 +1207,7 @@ def test_minimal_valid_participant(self): assert output is True def test_valid_participant_with_all_fields(self): + """Test valid participant with all fields.""" data = [ { "participant_id": "sub-user1", @@ -1197,3 +1281,19 @@ def test_invalid_handedness(self): output = validate_participants(data) assert output is False + + +class TestValidateDatatypeDescription: + def test_invalid_datatype_description(self): + data = ["ekg", "redcap_data", "oct", "invalid"] + + output = validate_datatype_dictionary(data) + + assert output is False + + def test_valid_datatype_description(self): + data = ["ekg", "redcap_data", "oct"] + + output = validate_datatype_dictionary(data) + + assert output is True