eva-sub-cli 0.6.1__tar.gz → 0.6.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.github/workflows/integration-tests.yml +3 -0
  2. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.github/workflows/publish.yml +5 -2
  3. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.github/workflows/tests.yml +5 -2
  4. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +3 -0
  5. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/PKG-INFO +2 -2
  6. eva_sub_cli-0.6.3/eva_sub_cli/_version.py +24 -0
  7. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/spreadsheet2json_conf.yaml +1 -0
  8. eva_sub_cli-0.6.3/eva_sub_cli/exceptions.py +40 -0
  9. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/cli.py +25 -27
  10. eva_sub_cli-0.6.3/eva_sub_cli/executables/format_metadata.py +42 -0
  11. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/xlsx2json.py +1 -11
  12. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/file_utils.py +0 -23
  13. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/nextflow/validation.nf +30 -3
  14. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/orchestrator.py +6 -49
  15. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/semantic_metadata.py +7 -3
  16. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/submission_ws.py +1 -1
  17. eva_sub_cli-0.6.3/eva_sub_cli/utils.py +72 -0
  18. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/validators/docker_validator.py +1 -1
  19. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/validators/validator.py +20 -10
  20. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/PKG-INFO +2 -2
  21. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/SOURCES.txt +4 -6
  22. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/entry_points.txt +1 -0
  23. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/requires.txt +1 -1
  24. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/pyproject.toml +2 -1
  25. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/requirements.txt +1 -1
  26. eva_sub_cli-0.6.3/tests/resources/EVA_Submission_test_with_links.xlsx +0 -0
  27. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_cli.py +10 -16
  28. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_file_utils.py +1 -32
  29. eva_sub_cli-0.6.3/tests/test_format_metadata.py +64 -0
  30. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_orchestrator.py +26 -9
  31. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_semantic_metadata.py +10 -0
  32. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_validator.py +39 -4
  33. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_xlsx2json.py +32 -7
  34. eva_sub_cli-0.6.1/eva_sub_cli/_version.py +0 -34
  35. eva_sub_cli-0.6.1/eva_sub_cli/exceptions/invalid_file_type_exception.py +0 -4
  36. eva_sub_cli-0.6.1/eva_sub_cli/exceptions/metadata_template_version_exception.py +0 -10
  37. eva_sub_cli-0.6.1/eva_sub_cli/exceptions/submission_not_found_exception.py +0 -4
  38. eva_sub_cli-0.6.1/eva_sub_cli/exceptions/submission_status_exception.py +0 -5
  39. eva_sub_cli-0.6.1/eva_sub_cli/exceptions/submission_upload_exception.py +0 -5
  40. eva_sub_cli-0.6.1/eva_sub_cli/utils.py +0 -20
  41. eva_sub_cli-0.6.1/eva_sub_cli/validators/__init__.py +0 -0
  42. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.github/workflows/publish_docs.yml +0 -0
  43. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/.gitignore +0 -0
  44. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/LICENSE +0 -0
  45. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/README.md +0 -0
  46. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/conda/build.sh +0 -0
  47. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/conda/meta.yaml +0 -0
  48. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docker/Dockerfile +0 -0
  49. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/README.md +0 -0
  50. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/_config.yml +0 -0
  51. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/how_to_submit.md +0 -0
  52. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/input_file_overview.md +0 -0
  53. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/installation.md +0 -0
  54. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/using_nextflow.md +0 -0
  55. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/docs/validation_overview.md +0 -0
  56. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/__init__.py +0 -0
  57. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/auth.py +0 -0
  58. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/call_home.py +0 -0
  59. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/date_utils.py +0 -0
  60. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
  61. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
  62. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/call_home_payload_schema.json +0 -0
  63. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/eva-biosamples.json +0 -0
  64. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/eva_logo.png +0 -0
  65. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/eva_schema.json +0 -0
  66. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/etc/spreadsheet2json_conf_V2.yaml +0 -0
  67. {eva_sub_cli-0.6.1/eva_sub_cli/exceptions → eva_sub_cli-0.6.3/eva_sub_cli/executables}/__init__.py +0 -0
  68. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
  69. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/check_metadata_semantics.py +0 -0
  70. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/evidence_type_checker.py +0 -0
  71. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/samples_checker.py +0 -0
  72. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/executables/trim_down.py +0 -0
  73. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
  74. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/file_validation.html +0 -0
  75. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
  76. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/project_details.html +0 -0
  77. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/report.html +0 -0
  78. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
  79. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
  80. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
  81. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/file_validation.txt +0 -0
  82. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
  83. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/project_details.txt +0 -0
  84. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/report.txt +0 -0
  85. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
  86. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
  87. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/metadata.py +0 -0
  88. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/report.py +0 -0
  89. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/submit.py +0 -0
  90. {eva_sub_cli-0.6.1/eva_sub_cli/executables → eva_sub_cli-0.6.3/eva_sub_cli/validators}/__init__.py +0 -0
  91. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/validators/native_validator.py +0 -0
  92. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
  93. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
  94. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/eva_sub_cli.egg-info/top_level.txt +0 -0
  95. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/pytest.ini +0 -0
  96. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/setup.cfg +0 -0
  97. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/setup.py +0 -0
  98. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/build_and_test_docker_locally.py +0 -0
  99. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/ignore_test_nextflow_validation.yml +0 -0
  100. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
  101. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test.json +0 -0
  102. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test.xlsx +0 -0
  103. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
  104. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  105. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
  106. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_with_asm_report.json +0 -0
  107. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_with_non_vcf_files.json +0 -0
  108. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx +0 -0
  109. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_with_project_accession.json +0 -0
  110. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/EVA_Submission_test_with_project_accession.xlsx +0 -0
  111. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
  112. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
  113. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/assembly_reports/input_passed.txt +0 -0
  114. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
  115. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/fasta_files/input_passed.fa +0 -0
  116. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/fasta_files/multi_seq.fa +0 -0
  117. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/metadata_with_filename.json +0 -0
  118. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_checker/evidence_type.yaml +0 -0
  119. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_checker/example1.vcf.gz +0 -0
  120. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_checker/example2.vcf +0 -0
  121. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_checker/example3.vcf +0 -0
  122. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_checker/metadata.json +0 -0
  123. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/allele_freq.vcf +0 -0
  124. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/fake_fasta.fa +0 -0
  125. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/genotype.vcf +0 -0
  126. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json +0 -0
  127. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json +0 -0
  128. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json +0 -0
  129. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json +0 -0
  130. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_metadata_json_report.html +0 -0
  131. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_metadata_json_report.txt +0 -0
  132. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_metadata_xlsx_report.html +0 -0
  133. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_metadata_xlsx_report.txt +0 -0
  134. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.html +0 -0
  135. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.txt +0 -0
  136. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +0 -0
  137. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +0 -0
  138. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
  139. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
  140. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
  141. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/metadata.json +0 -0
  142. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +0 -0
  143. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/file_info.txt +0 -0
  144. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
  145. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/input_passed_trim_down.yml +0 -0
  146. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
  147. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
  148. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +0 -0
  149. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
  150. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
  151. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
  152. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
  153. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/vcf_files/example2.vcf.gz +0 -0
  154. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/vcf_files/example2.vcf.gz.tbi +0 -0
  155. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/resources/vcf_files/input_passed.vcf +0 -0
  156. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_auth.py +0 -0
  157. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_call_home.py +0 -0
  158. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_check_fasta_insdc.py +0 -0
  159. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_docker_validator.py +0 -0
  160. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_evidence_type_checker.py +0 -0
  161. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_metadata.py +0 -0
  162. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_native_validator_sample_in_vcf.py +0 -0
  163. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_report.py +0 -0
  164. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_samples_checker.py +0 -0
  165. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_submit.py +0 -0
  166. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_trim_down.py +0 -0
  167. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_utils.py +0 -0
  168. {eva_sub_cli-0.6.1 → eva_sub_cli-0.6.3}/tests/test_validaton_results_parsers.py +0 -0
@@ -6,6 +6,9 @@ on:
6
6
  pull_request:
7
7
  branches: [ main]
8
8
 
9
+ permissions:
10
+ contents: read
11
+
9
12
  env:
10
13
  VCF_VALIDATOR_VERSION: "0.10.2"
11
14
  NXF_VER: "23.10.0"
@@ -5,12 +5,15 @@ on:
5
5
  tags:
6
6
  - '**'
7
7
 
8
+ permissions:
9
+ contents: read
10
+
8
11
  jobs:
9
12
  test:
10
13
  runs-on: ubuntu-latest
11
14
  strategy:
12
15
  matrix:
13
- python-version: ["3.9"]
16
+ python-version: ["3.11"]
14
17
  steps:
15
18
  - uses: actions/checkout@v4
16
19
  - name: Set up Python ${{ matrix.python-version }}
@@ -38,7 +41,7 @@ jobs:
38
41
  - name: Set up Python
39
42
  uses: actions/setup-python@v5
40
43
  with:
41
- python-version: '3.9'
44
+ python-version: '3.11'
42
45
  cache: pip
43
46
  cache-dependency-path: '**/pyproject.toml'
44
47
  - name: Install dependencies
@@ -4,14 +4,17 @@ on:
4
4
  push:
5
5
  branches: [ main ]
6
6
  pull_request:
7
- branches: [ main, add-validation-tasks ]
7
+ branches: [ main ]
8
+
9
+ permissions:
10
+ contents: read
8
11
 
9
12
  jobs:
10
13
  build:
11
14
  runs-on: ubuntu-latest
12
15
  strategy:
13
16
  matrix:
14
- python-version: ["3.9", "3.11", "3.12"]
17
+ python-version: ["3.11", "3.12"]
15
18
 
16
19
  steps:
17
20
  - uses: actions/checkout@v2
@@ -4,6 +4,9 @@ on:
4
4
  push:
5
5
  branches: [main]
6
6
 
7
+ permissions:
8
+ contents: read
9
+
7
10
  jobs:
8
11
  trigger-integration-tests:
9
12
  runs-on: ubuntu-latest
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eva_sub_cli
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: EBI EVA - validation and submission command line tool
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -19,7 +19,7 @@ Classifier: License :: OSI Approved :: Apache Software License
19
19
  Requires-Python: >=3.6
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: ebi_eva_common_pyutils==0.*,>=0.7.4
22
+ Requires-Dist: ebi_eva_common_pyutils>=0.7.4
23
23
  Requires-Dist: jinja2==3.*,>=3.0.0
24
24
  Requires-Dist: jsonschema==4.*
25
25
  Requires-Dist: openpyxl==3.*
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.6.3'
22
+ __version_tuple__ = version_tuple = (0, 6, 3)
23
+
24
+ __commit_id__ = commit_id = 'g1c826d931'
@@ -77,6 +77,7 @@ Analysis:
77
77
  Phasing: boolean
78
78
  Date: date
79
79
  Software: list
80
+ Link(s): list
80
81
 
81
82
  Sample:
82
83
  header_row: 3
@@ -0,0 +1,40 @@
1
+ class NoVcfsFoundException(Exception):
2
+ def __init__(self, message):
3
+ self.message = message
4
+ super().__init__(self.message)
5
+
6
+
7
+ class InvalidFileTypeError(Exception):
8
+ def __init__(self, message):
9
+ self.message = message
10
+ super().__init__(self.message)
11
+
12
+
13
+ class MetadataTemplateVersionException(Exception):
14
+ def __init__(self, message):
15
+ self.message = message
16
+ super().__init__(self.message)
17
+
18
+
19
+ class MetadataTemplateVersionNotFoundException(Exception):
20
+ def __init__(self, message):
21
+ self.message = message
22
+ super().__init__(self.message)
23
+
24
+
25
+ class SubmissionNotFoundException(Exception):
26
+ def __init__(self, message):
27
+ self.message = message
28
+ super().__init__(self.message)
29
+
30
+
31
+ class SubmissionStatusException(Exception):
32
+ def __init__(self, message):
33
+ self.message = message
34
+ super().__init__(self.message)
35
+
36
+
37
+ class SubmissionUploadException(Exception):
38
+ def __init__(self, message):
39
+ self.message = message
40
+ super().__init__(self.message)
@@ -2,8 +2,6 @@ import sys
2
2
 
3
3
  from requests import HTTPError
4
4
 
5
- from eva_sub_cli.exceptions.submission_upload_exception import SubmissionUploadException
6
-
7
5
  if not sys.warnoptions:
8
6
  import warnings
9
7
  warnings.simplefilter("ignore")
@@ -15,10 +13,8 @@ from ebi_eva_common_pyutils.logger import logging_config
15
13
 
16
14
  import eva_sub_cli
17
15
  from eva_sub_cli import orchestrator
18
- from eva_sub_cli.exceptions.metadata_template_version_exception import MetadataTemplateVersionException, \
19
- MetadataTemplateVersionNotFoundException
20
- from eva_sub_cli.exceptions.submission_status_exception import SubmissionStatusException
21
- from eva_sub_cli.exceptions.submission_not_found_exception import SubmissionNotFoundException
16
+ from eva_sub_cli.exceptions import MetadataTemplateVersionException, MetadataTemplateVersionNotFoundException, \
17
+ SubmissionStatusException, SubmissionNotFoundException, SubmissionUploadException, NoVcfsFoundException
22
18
  from eva_sub_cli.call_home import CallHomeClient
23
19
  from eva_sub_cli.file_utils import is_submission_dir_writable, DirLockError, DirLock
24
20
  from eva_sub_cli.orchestrator import VALIDATE, SUBMIT, DOCKER, NATIVE
@@ -130,48 +126,50 @@ def main():
130
126
  # Pass on all the arguments to the orchestrator
131
127
  orchestrator.orchestrate_process(call_home=call_home, **args.__dict__)
132
128
  except DirLockError as dle:
133
- print(f'Could not acquire the lock file for {args.submission_dir} because another process is using this '
134
- f'directory or a previous process did not terminate correctly. '
135
- f'If the problem persists, remove the lock file manually.')
129
+ logger.exception(f'Could not acquire the lock file for {args.submission_dir} because another process is using '
130
+ f'this directory or a previous process did not terminate correctly. '
131
+ f'If the problem persists, remove the lock file manually.')
136
132
  caught_exception = dle
137
133
  exit_status = 65
138
134
  except FileNotFoundError as fne:
139
- print(fne)
135
+ logger.exception(fne)
140
136
  caught_exception = fne
141
137
  exit_status = 66
138
+ except NoVcfsFoundException as nvfe:
139
+ logger.exception(f'{nvfe}. Please ensure that you have listed VCF files in the metadata (.vcf or .vcf.gz file '
140
+ f'extension), and that you have not modified the metadata template in any way.')
141
+ caught_exception = nvfe
142
+ exit_status = 67
142
143
  except SubmissionNotFoundException as snfe:
143
- print(f'{snfe}. Please contact EVA Helpdesk')
144
+ logger.exception(f'{snfe}. Please contact EVA Helpdesk')
144
145
  caught_exception = snfe
145
- exit_status = 67
146
+ exit_status = 68
146
147
  except SubmissionStatusException as sse:
147
- print(f'{sse}. Please try again later. If the problem persists, please contact EVA Helpdesk')
148
+ logger.exception(f'{sse}. Please try again later. If the problem persists, please contact EVA Helpdesk')
148
149
  caught_exception = sse
149
- exit_status = 68
150
+ exit_status = 69
150
151
  except MetadataTemplateVersionException as mte:
151
- print(mte)
152
+ logger.exception(mte)
152
153
  caught_exception = mte
153
- exit_status = 69
154
+ exit_status = 70
154
155
  except MetadataTemplateVersionNotFoundException as mte:
155
- print(mte)
156
+ logger.exception(mte)
156
157
  caught_exception = mte
157
- exit_status = 70
158
+ exit_status = 71
158
159
  except SubmissionUploadException as sue:
159
- print(sue)
160
+ logger.exception(sue)
160
161
  caught_exception = sue
161
- exit_status = 71
162
+ exit_status = 72
162
163
  except HTTPError as http_err:
163
- print(http_err)
164
+ logger.exception(http_err)
164
165
  if http_err.response is not None and http_err.response.text:
165
166
  print(http_err.response.text)
166
167
  caught_exception = http_err
167
- exit_status = 72
168
+ exit_status = 73
168
169
  except Exception as ex:
169
- print(ex)
170
+ logger.exception(ex)
170
171
  caught_exception = ex
171
- exit_status = 73
172
-
173
- if caught_exception:
174
- logger.exception(caught_exception)
172
+ exit_status = 74
175
173
 
176
174
  if call_home is not None:
177
175
  if exit_status == 0:
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import json
4
+ import shutil
5
+
6
+ from ebi_eva_common_pyutils.logger import logging_config
7
+ logger = logging_config.get_logger(__name__)
8
+
9
+ def format_experiment_type(json_file_input, json_file_output):
10
+ try:
11
+ with open(json_file_input, 'r') as input:
12
+ json_data = json.load(input)
13
+
14
+ for analysis_item in json_data.get("analysis", []):
15
+ original_experiment_type = analysis_item.get("experimentType", "")
16
+ logger.info(f"Formatting metadata - experiment type to capitalized - {original_experiment_type}")
17
+ experiment_type_capital = original_experiment_type.capitalize()
18
+ analysis_item["experimentType"] = experiment_type_capital or ""
19
+
20
+ with open(json_file_output, 'w') as output:
21
+ json.dump(json_data, output, indent=4)
22
+ return json_file_output
23
+
24
+ except (FileNotFoundError, json.JSONDecodeError, KeyError) as e:
25
+ # if the try block fails, copy the input file (because nextflow is expecting the output file).
26
+ logger.error(f"Failed to process JSON: {e}")
27
+ shutil.copy(json_file_input, json_file_output)
28
+ return None
29
+
30
+
31
+ def main():
32
+ arg_parser = argparse.ArgumentParser(
33
+ description='Formats experiment type for the metadata.')
34
+ arg_parser.add_argument('--metadata_json_input', required=True, dest='metadata_json_input',
35
+ help='EVA metadata json file INPUT')
36
+ arg_parser.add_argument('--metadata_json_output', required=True, dest='metadata_json_output',
37
+ help='EVA metadata json file OUTPUT')
38
+ args = arg_parser.parse_args()
39
+ format_experiment_type(args.metadata_json_input, args.metadata_json_output)
40
+
41
+ if __name__ == "__main__":
42
+ main()
@@ -9,8 +9,6 @@ from ebi_eva_common_pyutils.logger import logging_config
9
9
  from openpyxl.reader.excel import load_workbook
10
10
  from openpyxl.workbook import Workbook
11
11
 
12
- from eva_sub_cli.orchestrator import get_sub_cli_version, get_sub_cli_github_tags
13
-
14
12
  WORKSHEETS_KEY_NAME = 'worksheets'
15
13
  REQUIRED_HEADERS_KEY_NAME = 'required'
16
14
  OPTIONAL_HEADERS_KEY_NAME = 'optional'
@@ -259,8 +257,7 @@ class XlsxParser:
259
257
  # If the file could not be loaded at all, return without generating JSON.
260
258
  if not self.file_loaded:
261
259
  return
262
- # Include which version of the EVA schema we are using
263
- json_data = {'$schema': self.get_json_schema_link()}
260
+ json_data = {}
264
261
  for title in self.xlsx_conf[WORKSHEETS_KEY_NAME]:
265
262
  self.active_worksheet = title
266
263
  if title == PROJECT:
@@ -281,13 +278,6 @@ class XlsxParser:
281
278
  with open(output_json_file, 'w') as open_file:
282
279
  json.dump(json_data, open_file, cls=DateTimeEncoder)
283
280
 
284
- def get_json_schema_link(self):
285
- sub_cli_version = get_sub_cli_version()
286
- sub_cli_tags = get_sub_cli_github_tags()
287
- if sub_cli_version in sub_cli_tags:
288
- return f'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/refs/tags/v{sub_cli_version}/eva_sub_cli/etc/eva_schema.json'
289
- else:
290
- return 'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/main/eva_sub_cli/etc/eva_schema.json'
291
281
 
292
282
  def translate_header(self, title, header):
293
283
  if header in self.xlsx_conf[title].get(REQUIRED_HEADERS_KEY_NAME, {}):
@@ -1,7 +1,6 @@
1
1
  import glob
2
2
  import gzip
3
3
  import os
4
- import shutil
5
4
  import time
6
5
  from itertools import groupby
7
6
 
@@ -132,28 +131,6 @@ def _assess_vcf_evidence_type_manual(vcf_file):
132
131
  open_file.close()
133
132
 
134
133
 
135
- def backup_file_or_directory(file_name, max_backups=None):
136
- """
137
- Rename a file or directory by adding a '.1' at the end. If the '.1' file exists it move it to a '.2' and so on.
138
- Keep at most the specified number of backups, if None will keep all.
139
- """
140
- suffix = 1
141
- backup_name = f'{file_name}.{suffix}'
142
- while os.path.exists(backup_name):
143
- suffix += 1
144
- backup_name = f'{file_name}.{suffix}'
145
-
146
- for i in range(suffix, 1, -1):
147
- if max_backups and i > max_backups:
148
- if os.path.isfile(file_name):
149
- os.remove(f'{file_name}.{i - 1}')
150
- else:
151
- shutil.rmtree(f'{file_name}.{i - 1}')
152
- else:
153
- os.rename(f'{file_name}.{i - 1}', f'{file_name}.{i}')
154
- os.rename(file_name, file_name + '.1')
155
-
156
-
157
134
  def open_gzip_if_required(input_file, mode='r'):
158
135
  """Open a file in read mode using gzip if the file extension says .gz"""
159
136
  if input_file.endswith('.gz'):
@@ -42,7 +42,8 @@ params.python_scripts = [
42
42
  "fasta_checker": "check_fasta_insdc.py",
43
43
  "xlsx2json": "xlsx2json.py",
44
44
  "semantic_checker": "check_metadata_semantics.py",
45
- "trim_down": "trim_down.py"
45
+ "trim_down": "trim_down.py",
46
+ "format_metadata": "format_metadata.py"
46
47
  ]
47
48
  // prefix to prepend to all provided path
48
49
  params.base_dir = ""
@@ -66,7 +67,6 @@ schema_dir = file(projectDir).parent + '/etc'
66
67
  conversion_configuration = "${schema_dir}/$params.conversion_configuration_name"
67
68
 
68
69
 
69
-
70
70
  def joinBasePath(path) {
71
71
  if (path) {
72
72
  return params.base_dir + '/' + path
@@ -98,8 +98,11 @@ workflow {
98
98
  convert_xlsx_2_json(joinBasePath(params.metadata_xlsx))
99
99
  metadata_json = convert_xlsx_2_json.out.metadata_json
100
100
  } else {
101
- metadata_json = joinBasePath(params.metadata_json)
101
+ metadata_json = file(joinBasePath(params.metadata_json), checkIfExists:true)
102
102
  }
103
+
104
+ metadata_json_format(metadata_json)
105
+ metadata_json = metadata_json_format.out.metadata_formatted_json
103
106
  // File size and MD5
104
107
  generate_file_size_and_md5_digests(vcf_files)
105
108
  collect_file_size_and_md5(generate_file_size_and_md5_digests.out.file_size_and_digest_info.collect())
@@ -177,6 +180,7 @@ process check_vcf_valid {
177
180
  """
178
181
  trap 'if [[ \$? == 1 ]]; then exit 0; fi' EXIT
179
182
 
183
+ rm -rf ${output_dir}/vcf_format
180
184
  mkdir -p vcf_format
181
185
  $params.executable.vcf_validator -i $vcf -r text -o vcf_format --require-evidence > vcf_format/${vcf}.vcf_format.log 2>&1
182
186
  """
@@ -206,6 +210,7 @@ process check_vcf_reference {
206
210
  """
207
211
  trap 'if [[ \$? == 1 || \$? == 139 ]]; then exit 0; fi' EXIT
208
212
 
213
+ rm -rf ${output_dir}/assembly_check
209
214
  mkdir -p assembly_check
210
215
  $params.executable.vcf_assembly_checker -i $vcf -f $fasta $report_opt -r summary,text -o assembly_check --require-genbank > assembly_check/${vcf}.assembly_check.log 2>&1
211
216
  """
@@ -274,6 +279,28 @@ process convert_xlsx_2_json {
274
279
  """
275
280
  }
276
281
 
282
+ process metadata_json_format {
283
+
284
+ label 'short_time', 'small_mem'
285
+
286
+ publishDir output_dir,
287
+ overwrite: true,
288
+ mode: "copy"
289
+
290
+ input:
291
+ path(metadata_json)
292
+
293
+ output:
294
+ path "metadata_formatted.log", emit: metadata_formatted
295
+ path "metadata_formatted_case_insensitive.json", emit: metadata_formatted_json
296
+
297
+ script:
298
+ def output_json = "metadata_formatted_case_insensitive.json"
299
+ """
300
+ $params.python_scripts.format_metadata --metadata_json_input $metadata_json --metadata_json_output $output_json > metadata_formatted.log 2>&1
301
+ """
302
+ }
303
+
277
304
  process metadata_json_validation {
278
305
 
279
306
  label 'short_time', 'small_mem'
@@ -9,23 +9,18 @@ from ebi_eva_common_pyutils.config import WritableConfig
9
9
  from ebi_eva_common_pyutils.logger import logging_config
10
10
  from openpyxl.reader.excel import load_workbook
11
11
  from packaging import version
12
- from requests import HTTPError
13
- from retry import retry
14
12
 
15
- import eva_sub_cli
16
13
  from eva_sub_cli import MINIMUM_METADATA_XLSX_TEMPLATE_VERSION
17
14
  from eva_sub_cli import SUB_CLI_CONFIG_FILE, __version__
18
- from eva_sub_cli.exceptions.invalid_file_type_exception import InvalidFileTypeError
19
- from eva_sub_cli.exceptions.metadata_template_version_exception import MetadataTemplateVersionException, \
20
- MetadataTemplateVersionNotFoundException
21
- from eva_sub_cli.exceptions.submission_not_found_exception import SubmissionNotFoundException
22
- from eva_sub_cli.exceptions.submission_status_exception import SubmissionStatusException
15
+ from eva_sub_cli.exceptions import InvalidFileTypeError, MetadataTemplateVersionException, \
16
+ MetadataTemplateVersionNotFoundException, SubmissionNotFoundException, SubmissionStatusException, \
17
+ NoVcfsFoundException
23
18
  from eva_sub_cli.file_utils import is_vcf_file
24
19
  from eva_sub_cli.metadata import EvaMetadataJson
25
20
  from eva_sub_cli.submission_ws import SubmissionWSClient
26
21
  from eva_sub_cli.submit import StudySubmitter, SUB_CLI_CONFIG_KEY_SUBMISSION_ID, \
27
22
  SUB_CLI_CONFIG_KEY_SUBMISSION_UPLOAD_URL
28
- from eva_sub_cli.utils import get_project_title_from_ena
23
+ from eva_sub_cli.utils import get_project_title_from_ena, get_metadata_xlsx_template_link
29
24
  from eva_sub_cli.validators.docker_validator import DockerValidator
30
25
  from eva_sub_cli.validators.native_validator import NativeValidator
31
26
  from eva_sub_cli.validators.validator import READY_FOR_SUBMISSION_TO_EVA, ALL_VALIDATION_TASKS
@@ -115,6 +110,8 @@ def validate_vcf_mapping(vcf_mapping):
115
110
  :param vcf_mapping: iterable of triples (VCF file path, reference FASTA path, optional assembly report path)
116
111
  :return:
117
112
  """
113
+ if len(vcf_mapping) == 0:
114
+ raise NoVcfsFoundException('No VCF files detected in metadata')
118
115
  for vcf_file, fasta_file, report_file in vcf_mapping:
119
116
  if not (vcf_file and os.path.isfile(vcf_file)):
120
117
  raise FileNotFoundError(f'The variant file {vcf_file} does not exist, please check the file path.')
@@ -154,46 +151,6 @@ def get_project_and_vcf_fasta_mapping_from_metadata_json(metadata_json):
154
151
  return project_title, vcf_fasta_report_mapping
155
152
 
156
153
 
157
- def get_sub_cli_version():
158
- if version.parse(eva_sub_cli.__version__).is_devrelease:
159
- version_values = [int(v) for v in version.parse(eva_sub_cli.__version__).base_version.split('.')]
160
- major = version_values[0]
161
- minor = version_values[1] if len(version_values) > 1 else 0
162
- patch = version_values[2] if len(version_values) > 2 else 0
163
- if patch > 0:
164
- patch -= 1
165
- elif minor > 0:
166
- minor -= 1
167
- patch = 0
168
- elif major > 0:
169
- major -= 1
170
- minor = 0
171
- patch = 0
172
- return f"{major}.{minor}.{patch}"
173
- else:
174
- return version.parse(eva_sub_cli.__version__).base_version
175
-
176
-
177
- @retry(exceptions=(HTTPError,), tries=3, delay=2, backoff=1.2, jitter=(1, 3))
178
- def get_sub_cli_github_tags():
179
- url = f"https://api.github.com/repos/EBIvariation/eva-sub-cli/tags"
180
- response = requests.get(url)
181
- if response.status_code == 200:
182
- tags = [tag["name"][1:] for tag in response.json()]
183
- return tags
184
- else:
185
- return []
186
-
187
-
188
- def get_metadata_xlsx_template_link():
189
- sub_cli_version = get_sub_cli_version()
190
- sub_cli_tags = get_sub_cli_github_tags()
191
- if sub_cli_version in sub_cli_tags:
192
- return f'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/refs/tags/v{sub_cli_version}/eva_sub_cli/etc/EVA_Submission_template.xlsx'
193
- else:
194
- return 'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/main/eva_sub_cli/etc/EVA_Submission_template.xlsx'
195
-
196
-
197
154
  def verify_and_get_metadata_xlsx_version(metadata_xlsx, min_req_version):
198
155
  workbook = load_workbook(metadata_xlsx)
199
156
  instructions_sheet = workbook['PLEASE READ FIRST']
@@ -93,9 +93,13 @@ class SemanticMetadataChecker(AppLogger):
93
93
  self.check_taxonomy_code(project[TAX_ID_KEY], f'/{PROJECT_KEY}/{TAX_ID_KEY}')
94
94
  # Check sample taxonomies for novel samples
95
95
  for idx, sample in enumerate(self.metadata[SAMPLE_KEY]):
96
- if BIOSAMPLE_OBJECT_KEY in sample and TAX_ID_KEY in sample[BIOSAMPLE_OBJECT_KEY][CHARACTERISTICS_KEY]:
97
- self.check_taxonomy_code(sample[BIOSAMPLE_OBJECT_KEY][CHARACTERISTICS_KEY][TAX_ID_KEY][0]['text'],
98
- f'/{SAMPLE_KEY}/{idx}/{BIOSAMPLE_OBJECT_KEY}/{CHARACTERISTICS_KEY}/{TAX_ID_KEY}')
96
+ if BIOSAMPLE_OBJECT_KEY in sample:
97
+ if TAX_ID_KEY in sample[BIOSAMPLE_OBJECT_KEY][CHARACTERISTICS_KEY]:
98
+ self.check_taxonomy_code(sample[BIOSAMPLE_OBJECT_KEY][CHARACTERISTICS_KEY][TAX_ID_KEY][0]['text'],
99
+ f'/{SAMPLE_KEY}/{idx}/{BIOSAMPLE_OBJECT_KEY}/{CHARACTERISTICS_KEY}/{TAX_ID_KEY}')
100
+ else:
101
+ self.add_error(f'/{SAMPLE_KEY}/{idx}/{BIOSAMPLE_OBJECT_KEY}/{CHARACTERISTICS_KEY}/{TAX_ID_KEY}',
102
+ f"must have required property '{TAX_ID_KEY}'")
99
103
 
100
104
  def check_uniqueness_analysis_alias(self):
101
105
  analyses = self.metadata[ANALYSIS_KEY]
@@ -7,7 +7,7 @@ from retry import retry
7
7
 
8
8
  from eva_sub_cli import SUBMISSION_WS_VAR
9
9
  from eva_sub_cli.auth import get_auth
10
- from eva_sub_cli.exceptions.submission_upload_exception import SubmissionUploadException
10
+ from eva_sub_cli.exceptions import SubmissionUploadException
11
11
 
12
12
  DEFAULT_SUBMISSION_WS_URL = 'https://www.ebi.ac.uk/eva/webservices/submission-ws/v1/'
13
13
 
@@ -0,0 +1,72 @@
1
+ import requests
2
+ from packaging import version
3
+ from requests import HTTPError
4
+ from retry import retry
5
+
6
+ import eva_sub_cli
7
+ from ebi_eva_common_pyutils.ena_utils import download_xml_from_ena
8
+
9
+
10
+ def get_project_title_from_ena(project_accession):
11
+ try:
12
+ xml_root = download_xml_from_ena(f'https://www.ebi.ac.uk/ena/browser/api/xml/{project_accession}')
13
+ project_title = next(iter(xml_root.xpath('/PROJECT_SET/PROJECT/TITLE/text()')), None)
14
+ except HTTPError as e:
15
+ # We cannot currently differentiate between the service returning an error and the accession not existing
16
+ raise Exception(f"{project_accession} does not exist in ENA or is private")
17
+ except Exception as e:
18
+ raise Exception(f'Unexpected error occurred while getting project details from ENA for {project_accession}')
19
+
20
+ if not project_title:
21
+ raise Exception(f"{project_accession} does not exist in ENA or is private")
22
+
23
+ return project_title
24
+
25
+
26
+ def get_sub_cli_version():
27
+ if version.parse(eva_sub_cli.__version__).is_devrelease:
28
+ version_values = [int(v) for v in version.parse(eva_sub_cli.__version__).base_version.split('.')]
29
+ major = version_values[0]
30
+ minor = version_values[1] if len(version_values) > 1 else 0
31
+ patch = version_values[2] if len(version_values) > 2 else 0
32
+ if patch > 0:
33
+ patch -= 1
34
+ elif minor > 0:
35
+ minor -= 1
36
+ patch = 0
37
+ elif major > 0:
38
+ major -= 1
39
+ minor = 0
40
+ patch = 0
41
+ return f"{major}.{minor}.{patch}"
42
+ else:
43
+ return version.parse(eva_sub_cli.__version__).base_version
44
+
45
+
46
+ @retry(exceptions=(HTTPError,), tries=3, delay=2, backoff=1.2, jitter=(1, 3))
47
+ def get_sub_cli_github_tags():
48
+ url = f"https://api.github.com/repos/EBIvariation/eva-sub-cli/tags"
49
+ response = requests.get(url)
50
+ if response.status_code == 200:
51
+ tags = [tag["name"][1:] for tag in response.json()]
52
+ return tags
53
+ else:
54
+ return []
55
+
56
+
57
+ def get_metadata_xlsx_template_link():
58
+ sub_cli_version = get_sub_cli_version()
59
+ sub_cli_tags = get_sub_cli_github_tags()
60
+ if sub_cli_version in sub_cli_tags:
61
+ return f'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/refs/tags/v{sub_cli_version}/eva_sub_cli/etc/EVA_Submission_template.xlsx'
62
+ else:
63
+ return 'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/main/eva_sub_cli/etc/EVA_Submission_template.xlsx'
64
+
65
+
66
+ def get_json_schema_link():
67
+ sub_cli_version = get_sub_cli_version()
68
+ sub_cli_tags = get_sub_cli_github_tags()
69
+ if sub_cli_version in sub_cli_tags:
70
+ return f'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/refs/tags/v{sub_cli_version}/eva_sub_cli/etc/eva_schema.json'
71
+ else:
72
+ return 'https://raw.githubusercontent.com/EBIvariation/eva-sub-cli/main/eva_sub_cli/etc/eva_schema.json'
@@ -9,7 +9,7 @@ from retry import retry
9
9
  from eva_sub_cli.validators.validator import Validator, ALL_VALIDATION_TASKS
10
10
 
11
11
  default_container_image = 'ebivariation/eva-sub-cli'
12
- default_container_tag = 'v0.0.12'
12
+ default_container_tag = 'v0.0.13'
13
13
  container_validation_dir = '/opt/vcf_validation'
14
14
  container_validation_output_dir = 'vcf_validation_output'
15
15