eva-sub-cli 0.6.5__tar.gz → 0.6.7__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 (175) hide show
  1. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/PKG-INFO +1 -1
  2. eva_sub_cli-0.6.7/docs/common_metadata_errors.md +116 -0
  3. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/_version.py +3 -3
  4. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/auth.py +5 -1
  5. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/eva_schema.json +95 -86
  6. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/exceptions.py +36 -0
  7. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/cli.py +47 -27
  8. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/xlsx2json.py +8 -4
  9. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/file_utils.py +3 -5
  10. eva_sub_cli-0.6.7/eva_sub_cli/jinja_templates/html/file_validation.html +89 -0
  11. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/report.html +31 -11
  12. eva_sub_cli-0.6.7/eva_sub_cli/jinja_templates/text/file_validation.txt +55 -0
  13. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/report.txt +36 -15
  14. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/metadata.py +3 -1
  15. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/orchestrator.py +16 -10
  16. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/semantic_metadata.py +10 -2
  17. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/submit.py +3 -2
  18. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/validators/docker_validator.py +13 -10
  19. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/validators/native_validator.py +3 -1
  20. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/validators/validator.py +163 -58
  21. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/PKG-INFO +1 -1
  22. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/SOURCES.txt +4 -0
  23. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/scm_file_list.json +132 -128
  24. eva_sub_cli-0.6.7/eva_sub_cli.egg-info/scm_version.json +8 -0
  25. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test.json +1 -1
  26. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test.xlsx +0 -0
  27. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
  28. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  29. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test_with_asm_report.json +1 -1
  30. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test_with_formula.xlsx +0 -0
  31. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test_with_links.xlsx +0 -0
  32. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test_with_non_vcf_files.json +1 -1
  33. eva_sub_cli-0.6.7/tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx +0 -0
  34. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/metadata_with_filename.json +1 -1
  35. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_metadata_json_report.html +49 -49
  36. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_metadata_json_report.txt +20 -20
  37. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_metadata_xlsx_report.html +49 -49
  38. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_metadata_xlsx_report.txt +20 -20
  39. eva_sub_cli-0.6.7/tests/resources/validation_reports/expected_report_metadata_json_crashed.html +147 -0
  40. eva_sub_cli-0.6.7/tests/resources/validation_reports/expected_report_metadata_json_crashed.txt +47 -0
  41. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.html +3 -0
  42. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_report_metadata_json_process_not_run.txt +3 -0
  43. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.html +49 -49
  44. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/expected_shallow_metadata_xlsx_report.txt +20 -20
  45. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/metadata_validation.txt +1 -1
  46. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_cli.py +9 -9
  47. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_metadata.py +2 -1
  48. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_orchestrator.py +4 -4
  49. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_report.py +58 -20
  50. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_semantic_metadata.py +50 -0
  51. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_validator.py +258 -21
  52. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_xlsx2json.py +51 -1
  53. eva_sub_cli-0.6.5/eva_sub_cli/jinja_templates/html/file_validation.html +0 -93
  54. eva_sub_cli-0.6.5/eva_sub_cli/jinja_templates/text/file_validation.txt +0 -60
  55. eva_sub_cli-0.6.5/eva_sub_cli.egg-info/scm_version.json +0 -8
  56. eva_sub_cli-0.6.5/tests/resources/EVA_Submission_test.xlsx +0 -0
  57. eva_sub_cli-0.6.5/tests/resources/EVA_Submission_test_V2.xlsx +0 -0
  58. eva_sub_cli-0.6.5/tests/resources/EVA_Submission_test_fails.xlsx +0 -0
  59. eva_sub_cli-0.6.5/tests/resources/EVA_Submission_test_with_links.xlsx +0 -0
  60. eva_sub_cli-0.6.5/tests/resources/EVA_Submission_test_with_non_vcf_files.xlsx +0 -0
  61. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.github/workflows/integration-tests.yml +0 -0
  62. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.github/workflows/publish.yml +0 -0
  63. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.github/workflows/publish_docs.yml +0 -0
  64. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.github/workflows/tests.yml +0 -0
  65. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.github/workflows/trigger-eva-sub-cli-integration-tests.yml +0 -0
  66. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/.gitignore +0 -0
  67. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/LICENSE +0 -0
  68. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/README.md +0 -0
  69. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/conda/build.sh +0 -0
  70. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/conda/meta.yaml +0 -0
  71. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docker/Dockerfile +0 -0
  72. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/README.md +0 -0
  73. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/_config.yml +0 -0
  74. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/common_vcf_errors.md +0 -0
  75. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/how_to_submit.md +0 -0
  76. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/input_file_overview.md +0 -0
  77. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/installation.md +0 -0
  78. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/using_nextflow.md +0 -0
  79. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/docs/validation_overview.md +0 -0
  80. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/__init__.py +0 -0
  81. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/call_home.py +0 -0
  82. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/date_utils.py +0 -0
  83. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/EVA_Submission_Example.xlsx +0 -0
  84. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/EVA_Submission_template.xlsx +0 -0
  85. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/call_home_payload_schema.json +0 -0
  86. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/eva-biosamples.json +0 -0
  87. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/eva_logo.png +0 -0
  88. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/spreadsheet2json_conf.yaml +0 -0
  89. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/etc/spreadsheet2json_conf_V2.yaml +0 -0
  90. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/__init__.py +0 -0
  91. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/check_fasta_insdc.py +0 -0
  92. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/check_metadata_semantics.py +0 -0
  93. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/evidence_type_checker.py +0 -0
  94. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/format_metadata.py +0 -0
  95. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/samples_checker.py +0 -0
  96. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/executables/trim_down.py +0 -0
  97. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/fasta_check.html +0 -0
  98. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/metadata_validation.html +0 -0
  99. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/project_details.html +0 -0
  100. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/sample_name_check.html +0 -0
  101. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/html/shallow_validation.html +0 -0
  102. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/fasta_check.txt +0 -0
  103. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/metadata_validation.txt +0 -0
  104. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/project_details.txt +0 -0
  105. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/sample_name_check.txt +0 -0
  106. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/jinja_templates/text/shallow_validation.txt +0 -0
  107. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/nextflow/validation.nf +0 -0
  108. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/report.py +0 -0
  109. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/submission_ws.py +0 -0
  110. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/utils.py +0 -0
  111. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/validators/__init__.py +0 -0
  112. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli/validators/validation_results_parsers.py +0 -0
  113. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/dependency_links.txt +0 -0
  114. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/entry_points.txt +0 -0
  115. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/requires.txt +0 -0
  116. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/eva_sub_cli.egg-info/top_level.txt +0 -0
  117. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/pyproject.toml +0 -0
  118. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/pytest.ini +0 -0
  119. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/requirements.txt +0 -0
  120. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/setup.cfg +0 -0
  121. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/setup.py +0 -0
  122. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/build_and_test_docker_locally.py +0 -0
  123. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/ignore_test_nextflow_validation.yml +0 -0
  124. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_Docker_Test.xlsx +0 -0
  125. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test_version_missing.xlsx +0 -0
  126. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test_with_project_accession.json +0 -0
  127. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/EVA_Submission_test_with_project_accession.xlsx +0 -0
  128. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/assembly_check/invalid.vcf.assembly_check.log +0 -0
  129. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/assembly_check/invalid.vcf.text_assembly_report.txt +0 -0
  130. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/assembly_reports/input_passed.txt +0 -0
  131. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/fasta_files/Saccharomyces_cerevisiae_I.fa +0 -0
  132. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/fasta_files/input_passed.fa +0 -0
  133. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/fasta_files/multi_seq.fa +0 -0
  134. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_checker/evidence_type.yaml +0 -0
  135. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_checker/example1.vcf.gz +0 -0
  136. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_checker/example2.vcf +0 -0
  137. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_checker/example3.vcf +0 -0
  138. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_checker/metadata.json +0 -0
  139. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/allele_freq.vcf +0 -0
  140. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/fake_fasta.fa +0 -0
  141. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/genotype.vcf +0 -0
  142. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/metadata_af_no_sample_in_vcf.json +0 -0
  143. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/metadata_af_with_sample_in_vcf.json +0 -0
  144. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/metadata_genotype_no_sample_in_vcf.json +0 -0
  145. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/sample_in_vcf_check/metadata_genotype_with_sample_in_vcf.json +0 -0
  146. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.assembly_check.log +0 -0
  147. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.text_assembly_report.1680102476700.txt +0 -0
  148. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/assembly_check/input_passed.vcf.valid_assembly_report.1680102476700.txt +0 -0
  149. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/metadata.json +0 -0
  150. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/evidence_type_checker.yml +0 -0
  151. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/file_info.txt +0 -0
  152. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/input_passed.fa_check.yml +0 -0
  153. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/input_passed_trim_down.yml +0 -0
  154. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/metadata_conversion_errors.yml +0 -0
  155. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/metadata_semantic_check.yml +0 -0
  156. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/other_validations/sample_checker.yml +0 -0
  157. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.db +0 -0
  158. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.errors.1680102476854.txt +0 -0
  159. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/validation_reports/validation_output/vcf_format/input_passed.vcf.vcf_format.log +0 -0
  160. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/vcf_files/example2.vcf.gz +0 -0
  161. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/vcf_files/example2.vcf.gz.tbi +0 -0
  162. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/resources/vcf_files/input_passed.vcf +0 -0
  163. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_auth.py +0 -0
  164. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_call_home.py +0 -0
  165. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_check_fasta_insdc.py +0 -0
  166. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_docker_validator.py +0 -0
  167. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_evidence_type_checker.py +0 -0
  168. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_file_utils.py +0 -0
  169. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_format_metadata.py +0 -0
  170. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_native_validator_sample_in_vcf.py +0 -0
  171. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_samples_checker.py +0 -0
  172. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_submit.py +0 -0
  173. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_trim_down.py +0 -0
  174. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_utils.py +0 -0
  175. {eva_sub_cli-0.6.5 → eva_sub_cli-0.6.7}/tests/test_validaton_results_parsers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eva_sub_cli
3
- Version: 0.6.5
3
+ Version: 0.6.7
4
4
  Summary: EBI EVA - validation and submission command line tool
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -0,0 +1,116 @@
1
+ # **Frequently encountered metadata errors**
2
+
3
+ This section provides a curated overview of some of the common metadata errors. Each error is illustrated with a real validation output example, followed by a brief description of the error and the expected resolution for EVA submissions.
4
+
5
+ ## 1. Missing mandatory metadata
6
+
7
+ **Example Validation Error**
8
+
9
+ | **Sheet** | **Row** | **Column** | **Description** |
10
+ |---|---:|---|---|
11
+ | **Submitter Details** | **2** | **Center** | Column "Center" is not populated |
12
+
13
+ **Description**
14
+
15
+ The Center field is required but has been left empty in the Submitter Details sheet.
16
+
17
+ **Resolution**
18
+
19
+ Populate all mandatory fields indicated in bold. EVA expects these fields to contain a valid value and not be left blank.
20
+
21
+ For the Center field, provide the name of the submitting center/institution.
22
+
23
+ ## 2. Invalid metadata values
24
+
25
+ **Example Validation Error**
26
+
27
+ | Sheet | Row | Column | Description |
28
+ |---|---:|---|---|
29
+ | **Sample** | **3** | **Scientific Name** | Species *Homo sapens* does not match taxonomy 9606 (*Homo sapiens*). |
30
+
31
+ **Description**
32
+
33
+ The Scientific Name does not match the species associated with the submitted Taxonomy ID. In the above example, taxonomy ID 9606 corresponds to Homo sapiens and not Homo sapens.
34
+
35
+ **Resolution**
36
+
37
+ Check that the metadata value is valid and follows the expected format or controlled vocabulary.
38
+
39
+ ## 3. Invalid metadata format
40
+
41
+ **Example Validation Error**
42
+
43
+ | Sheet | Row | Column | Description |
44
+ | --- | --- | --- | --- |
45
+ | **Submitter Details** | **2** | **Email Address** | Must match the `email` format. |
46
+
47
+ **Description**
48
+
49
+ The email address provided in the Submitter Details sheet does not match the expected email address format.
50
+
51
+ **Resolution**
52
+
53
+ Enter a valid email address in the Email Address field, for example, name@example.com.
54
+
55
+ For similar metadata validation errors, check the value against the format or allowed values expected by EVA and correct the metadata accordingly.
56
+
57
+ ## 4. Project or Sample Not Publicly Accessible
58
+
59
+ **Example Validation Error**
60
+
61
+ ```text
62
+ Exception: PRJEBXXXXXX does not exist in ENA or is private
63
+
64
+ SAMNXXXXXXXX does not exist or is private
65
+
66
+ ```
67
+
68
+ **Description**
69
+
70
+ The submitted project or sample accession cannot be found in ENA or is not publicly accessible. This may occur when the accession is incorrect, does not exist, or the corresponding object is still private.
71
+
72
+ **Resolution**
73
+
74
+ EVA cannot access or validate private objects. Make sure the project or sample has been released publicly before submitting it to EVA for validation.
75
+
76
+ ## 5. BioSamples issued by NCBI : geographic location/collection date issue
77
+
78
+ **Example Validation Error**
79
+
80
+ | Sheet | Row | Column | Description |
81
+ |---|---:|---|---|
82
+ | **Sample** | **4** | **Sample Accession** | Error validating existing sample SAMN47377199: must have required property **'collection date'**. |
83
+ | **Sample** | **4** | **Sample Accession** | Error validating existing sample SAMN47377199: must have required property **'geographic location (country and/or sea)'**. |
84
+
85
+ **Description**
86
+
87
+ This error is due to a difference in reporting geographical location and collection date between NCBI BioSamples and ENA BioSamples. NCBI BioSamples uses property names "geo_loc_name" and "collection_date", whereas ENA uses "geographic location (country and/or sea)" and "collection date". EVA validates BioSamples against ENA's definition, which makes reusing NCBI BioSamples in a submission to EVA difficult to automate at the moment.
88
+
89
+ **Resolution**
90
+
91
+ Once you have validated the rest of the data, contact eva-helpdesk@ebi.ac.uk to submit the data, as this will require manual intervention. Both NCBI and ENA are aware of this issue and we are working towards fixing this.
92
+
93
+ ## 6. Either/Or Fields Completed Incorrectly
94
+
95
+ **Description**
96
+
97
+ Some metadata fields are highlighted in green to indicate an either/or requirement. Only one of the specified options should be completed.
98
+
99
+ For example, in the Project tab, the submitter should complete either the Pre-registered Project section or the New Project section. Both sections should not be completed.
100
+
101
+ **Resolution**
102
+
103
+ When fields are highlighted in green, check the available options and complete only the section that applies to the submission. Leave the other option blank.
104
+
105
+
106
+ ## 7. Publication Field Not Completed Correctly
107
+
108
+ **Description**
109
+
110
+ The Publication(s) field is optional, but when provided, the publication must be and given in the expected DB format. An example valid entry would be: PubMed:23128226
111
+
112
+ **Resolution**
113
+
114
+ If publications related to the project are available, enter them using the required DB format, for example, PubMed:23128226. Multiple publications should be separated by commas. For example: PubMed:23128226, PubMed:223445.
115
+
116
+ If there are no relevant publications, the field can be left blank and can be added later by contacting the EVA helpdesk team.
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.6.5'
22
- __version_tuple__ = version_tuple = (0, 6, 5)
21
+ __version__ = version = '0.6.7'
22
+ __version_tuple__ = version_tuple = (0, 6, 7)
23
23
 
24
- __commit_id__ = commit_id = 'ge5181ff56'
24
+ __commit_id__ = commit_id = 'g1607240b0'
@@ -8,6 +8,7 @@ from ebi_eva_common_pyutils.logger import AppLogger
8
8
  from urllib3.exceptions import ResponseError
9
9
 
10
10
  from eva_sub_cli import LSRI_CLIENT_ID, ENA_WEBIN_ACCOUNT_VAR, ENA_WEBIN_PASSWORD_VAR
11
+ from eva_sub_cli.exceptions import WebinBadCredentialsException
11
12
 
12
13
  ENA_AUTH_URL = "https://www.ebi.ac.uk/ena/submit/webin/auth/token"
13
14
  LSRI_AUTH_URL = "https://www.ebi.ac.uk/eva/v1/submission/auth/lsri"
@@ -69,8 +70,11 @@ class WebinAuth(AppLogger):
69
70
  if response.status_code == 200:
70
71
  self.info("Webin authentication successful!")
71
72
  return response.text
73
+ elif response.status_code == 401:
74
+ raise WebinBadCredentialsException('Could not authenticate with ENA Webin. Please check your credentials '
75
+ 'and try again.')
72
76
  else:
73
- raise ResponseError('Webin Authentication Error')
77
+ raise ResponseError(f'Could not authenticate with ENA Webin: {response.status_code}, {response.text}')
74
78
 
75
79
  def _get_webin_username_password(self):
76
80
  username = self.cmd_line_username
@@ -64,84 +64,90 @@
64
64
  }
65
65
  },
66
66
  "project": {
67
- "oneOf": [
68
- {
69
- "type": "object",
70
- "required": [
71
- "projectAccession"
72
- ],
73
- "properties": {
74
- "projectAccession": {
75
- "$ref": "#/definitions/projectAccession"
76
- }
67
+ "type": "object",
68
+ "if": {
69
+ "required": [
70
+ "projectAccession"
71
+ ]
72
+ },
73
+ "then": {
74
+ "properties": {
75
+ "projectAccession": {
76
+ "$ref": "#/definitions/projectAccession"
77
77
  }
78
- },
79
- {
80
- "type": "object",
81
- "description": "General information about the Project",
82
- "required": [
83
- "title",
84
- "description",
85
- "taxId",
86
- "centre"
87
- ],
88
- "properties": {
89
- "title": {
90
- "type": "string",
91
- "description": "Title of the project",
92
- "maxLength": 500
93
- },
94
- "description": {
95
- "type": "string",
96
- "description": "Description of the project",
97
- "maxLength": 5000
98
- },
99
- "centre": {
100
- "type": "string",
101
- "description": "Centre, institute or company submitting the project"
102
- },
103
- "taxId": {
104
- "type": "number",
105
- "description": "Taxonomy ID of the species associated with the project (found here: http://www.ncbi.nlm.nih.gov/taxonomy)"
106
- },
107
- "publications": {
108
- "type": "array",
109
- "items": {
110
- "type": "string",
111
- "pattern": "^[^:,]+?:[^:,]+?$"
112
- }
113
- },
114
- "parentProject": {
115
- "$ref": "#/definitions/projectAccession"
116
- },
117
- "childProjects": {
118
- "type": "array",
119
- "items": {
120
- "$ref": "#/definitions/projectAccession"
121
- }
122
- },
123
- "peerProjects": {
124
- "type": "array",
125
- "items": {
126
- "$ref": "#/definitions/projectAccession"
127
- }
128
- },
129
- "links": {
130
- "type": "array",
131
- "items": {
132
- "type": "string"
133
- }
134
- },
135
- "holdDate": {
78
+ }
79
+ },
80
+ "else": {
81
+ "description": "General information about the Project",
82
+ "required": [
83
+ "title",
84
+ "description",
85
+ "taxId",
86
+ "centre"
87
+ ],
88
+ "properties": {
89
+ "title": {
90
+ "type": "string",
91
+ "description": "Title of the project",
92
+ "minLength": 20,
93
+ "maxLength": 250
94
+ },
95
+ "description": {
96
+ "type": "string",
97
+ "description": "Description of the project",
98
+ "minLength": 20,
99
+ "maxLength": 4000
100
+ },
101
+ "centre": {
102
+ "type": "string",
103
+ "description": "Centre, institute or company submitting the project"
104
+ },
105
+ "taxId": {
106
+ "type": "number",
107
+ "description": "Taxonomy ID of the species associated with the project (found here: http://www.ncbi.nlm.nih.gov/taxonomy)"
108
+ },
109
+ "publications": {
110
+ "type": "array",
111
+ "description": "Publications associated with the project, each given as <database>:<identifier>",
112
+ "items": {
136
113
  "type": "string",
137
- "format": "date",
114
+ "pattern": "^[^:,]+?:[^:,]+?$",
138
115
  "examples": [
139
- "2018-11-13"
116
+ "DOI:10.1093/nar/gkw1121",
117
+ "PMID:24565421"
140
118
  ]
141
119
  }
120
+ },
121
+ "parentProject": {
122
+ "$ref": "#/definitions/projectAccession"
123
+ },
124
+ "childProjects": {
125
+ "type": "array",
126
+ "items": {
127
+ "$ref": "#/definitions/projectAccession"
128
+ }
129
+ },
130
+ "peerProjects": {
131
+ "type": "array",
132
+ "items": {
133
+ "$ref": "#/definitions/projectAccession"
134
+ }
135
+ },
136
+ "links": {
137
+ "type": "array",
138
+ "items": {
139
+ "type": "string"
140
+ }
141
+ },
142
+ "holdDate": {
143
+ "type": "string",
144
+ "format": "date",
145
+ "examples": [
146
+ "2018-11-13"
147
+ ]
142
148
  }
143
149
  }
144
- ]
150
+ }
145
151
  },
146
152
  "analysis": {
147
153
  "type": "array",
@@ -307,21 +313,24 @@
307
313
  "minItems": 1,
308
314
  "items": {
309
315
  "type": "object",
310
- "oneOf": [
311
- {
312
- "required": [
313
- "analysisAlias",
314
- "sampleInVCF",
315
- "bioSampleAccession"
316
- ]
317
- },
318
- {
319
- "required": [
320
- "analysisAlias",
321
- "bioSampleObject"
322
- ]
323
- }
324
- ],
316
+ "if": {
317
+ "required": [
318
+ "bioSampleAccession"
319
+ ]
320
+ },
321
+ "then": {
322
+ "required": [
323
+ "analysisAlias",
324
+ "sampleInVCF",
325
+ "bioSampleAccession"
326
+ ]
327
+ },
328
+ "else": {
329
+ "required": [
330
+ "analysisAlias",
331
+ "bioSampleObject"
332
+ ]
333
+ },
325
334
  "properties": {
326
335
  "analysisAlias": {
327
336
  "type": "array",
@@ -38,3 +38,39 @@ class SubmissionUploadException(Exception):
38
38
  def __init__(self, message):
39
39
  self.message = message
40
40
  super().__init__(self.message)
41
+
42
+
43
+ class DirLockError(Exception):
44
+ def __init__(self, message):
45
+ self.message = message
46
+ super().__init__(self.message)
47
+
48
+
49
+ class UserFileNotFoundException(Exception):
50
+ def __init__(self, message):
51
+ self.message = message
52
+ super().__init__(self.message)
53
+
54
+
55
+ class DependencyNotFoundException(Exception):
56
+ def __init__(self, message):
57
+ self.message = message
58
+ super().__init__(self.message)
59
+
60
+
61
+ class WebinBadCredentialsException(Exception):
62
+ def __init__(self, message):
63
+ self.message = message
64
+ super().__init__(self.message)
65
+
66
+
67
+ class InvalidSubmissionException(Exception):
68
+ def __init__(self, message):
69
+ self.message = message
70
+ super().__init__(self.message)
71
+
72
+
73
+ class DockerValidatorException(Exception):
74
+ def __init__(self, message):
75
+ self.message = message
76
+ super().__init__(self.message)
@@ -15,7 +15,9 @@ import eva_sub_cli
15
15
  from eva_sub_cli import ENA_WEBIN_ACCOUNT_VAR, ENA_WEBIN_PASSWORD_VAR
16
16
  from eva_sub_cli import orchestrator
17
17
  from eva_sub_cli.exceptions import MetadataTemplateVersionException, MetadataTemplateVersionNotFoundException, \
18
- SubmissionStatusException, SubmissionNotFoundException, SubmissionUploadException, NoVcfsFoundException
18
+ SubmissionStatusException, SubmissionNotFoundException, SubmissionUploadException, NoVcfsFoundException, \
19
+ UserFileNotFoundException, DependencyNotFoundException, WebinBadCredentialsException, InvalidFileTypeError, \
20
+ InvalidSubmissionException, DockerValidatorException
19
21
  from eva_sub_cli.call_home import CallHomeClient
20
22
  from eva_sub_cli.file_utils import is_submission_dir_writable, DirLockError, DirLock
21
23
  from eva_sub_cli.orchestrator import VALIDATE, SUBMIT, DOCKER, NATIVE
@@ -126,51 +128,69 @@ def main():
126
128
  logging_config.add_file_handler(os.path.join(args.submission_dir, 'eva_submission.log'), logging.DEBUG)
127
129
  # Pass on all the arguments to the orchestrator
128
130
  orchestrator.orchestrate_process(call_home=call_home, **args.__dict__)
131
+
132
+ # User errors: not displayed as exceptions, call-home records as failure with no exception
129
133
  except DirLockError as dle:
130
- logger.exception(f'Could not acquire the lock file for {args.submission_dir} because another process is using '
131
- f'this directory or a previous process did not terminate correctly. '
132
- f'If the problem persists, remove the lock file manually.')
133
- caught_exception = dle
134
- exit_status = 65
134
+ print(f'Could not acquire the lock file for {args.submission_dir} because another process is using this '
135
+ f'directory or a previous process did not terminate correctly. If the problem persists, remove the lock '
136
+ f'file manually.')
137
+ exit_status = 101
138
+ except NoVcfsFoundException as nvfe:
139
+ print(nvfe.message)
140
+ exit_status = 102
141
+ except MetadataTemplateVersionException as mte:
142
+ print(mte.message)
143
+ exit_status = 103
144
+ except MetadataTemplateVersionNotFoundException as mte:
145
+ print(mte.message)
146
+ exit_status = 104
147
+ except UserFileNotFoundException as ufne:
148
+ print(ufne.message)
149
+ exit_status = 105
150
+ except InvalidFileTypeError as ife:
151
+ print(ife.message)
152
+ exit_status = 106
153
+ except DependencyNotFoundException as dnfe:
154
+ print(dnfe.message)
155
+ exit_status = 107
156
+ except WebinBadCredentialsException as wae:
157
+ print(wae.message)
158
+ exit_status = 108
159
+ except InvalidSubmissionException as ise:
160
+ print(ise.message)
161
+ exit_status = 109
162
+
163
+ # Process errors: displayed as exceptions and sent to call-home
135
164
  except FileNotFoundError as fne:
136
165
  logger.exception(fne)
137
166
  caught_exception = fne
138
- exit_status = 66
139
- except NoVcfsFoundException as nvfe:
140
- logger.exception(f'{nvfe}. Please ensure that you have listed VCF files in the metadata (.vcf or .vcf.gz file '
141
- f'extension), and that you have not modified the metadata template in any way.')
142
- caught_exception = nvfe
143
- exit_status = 67
167
+ exit_status = 201
144
168
  except SubmissionNotFoundException as snfe:
145
- logger.exception(f'{snfe}. Please contact EVA Helpdesk')
169
+ logger.exception(snfe)
146
170
  caught_exception = snfe
147
- exit_status = 68
171
+ exit_status = 202
148
172
  except SubmissionStatusException as sse:
149
- logger.exception(f'{sse}. Please try again later. If the problem persists, please contact EVA Helpdesk')
173
+ logger.exception(sse)
150
174
  caught_exception = sse
151
- exit_status = 69
152
- except MetadataTemplateVersionException as mte:
153
- logger.exception(mte)
154
- caught_exception = mte
155
- exit_status = 70
156
- except MetadataTemplateVersionNotFoundException as mte:
157
- logger.exception(mte)
158
- caught_exception = mte
159
- exit_status = 71
175
+ exit_status = 203
160
176
  except SubmissionUploadException as sue:
161
177
  logger.exception(sue)
162
178
  caught_exception = sue
163
- exit_status = 72
179
+ exit_status = 204
164
180
  except HTTPError as http_err:
165
181
  logger.exception(http_err)
166
182
  if http_err.response is not None and http_err.response.text:
167
183
  print(http_err.response.text)
168
184
  caught_exception = http_err
169
- exit_status = 73
185
+ exit_status = 205
186
+ except DockerValidatorException as dve:
187
+ logger.exception(dve)
188
+ caught_exception = dve
189
+ exit_status = 206
170
190
  except Exception as ex:
171
191
  logger.exception(ex)
172
192
  caught_exception = ex
173
- exit_status = 74
193
+ exit_status = 299
174
194
 
175
195
  if call_home is not None:
176
196
  if exit_status == 0:
@@ -51,7 +51,7 @@ class XlsxParser:
51
51
  with open(conf_filename, 'r') as conf_file:
52
52
  self.xlsx_conf = yaml.safe_load(conf_file)
53
53
  try:
54
- self.workbook = load_workbook(xlsx_filename, read_only=True)
54
+ self.workbook = load_workbook(xlsx_filename, read_only=True, data_only=True)
55
55
  except Exception as e:
56
56
  self.add_error(f'Error loading {xlsx_filename}: {repr(e)}')
57
57
  self.file_loaded = False
@@ -165,9 +165,13 @@ class XlsxParser:
165
165
  cell = row[header_index]
166
166
  if cell.value is not None:
167
167
  has_notnull = True
168
- data[header] = self.trim_value(self.cast_value(
169
- cell.value, self.xlsx_conf[worksheet].get(CAST_KEY_NAME, {}).get(header)
170
- ))
168
+ try:
169
+ value = self.cast_value(
170
+ cell.value, self.xlsx_conf[worksheet].get(CAST_KEY_NAME, {}).get(header)
171
+ )
172
+ except Exception as e:
173
+ value = cell.value
174
+ data[header] = self.trim_value(value)
171
175
 
172
176
  if has_notnull:
173
177
  data['row_num'] = self.row_offset[worksheet]
@@ -7,6 +7,8 @@ from itertools import groupby
7
7
  import pysam
8
8
  from ebi_eva_common_pyutils.logger import logging_config
9
9
 
10
+ from eva_sub_cli.exceptions import DirLockError
11
+
10
12
  logger = logging_config.get_logger(__name__)
11
13
 
12
14
 
@@ -158,10 +160,6 @@ def fasta_iter(input_fasta):
158
160
  yield (headerStr, seq)
159
161
 
160
162
 
161
- class DirLockError(Exception):
162
- pass
163
-
164
-
165
163
  class DirLock(object):
166
164
  _SPIN_PERIOD_SECONDS = 0.05
167
165
 
@@ -183,7 +181,7 @@ class DirLock(object):
183
181
  break
184
182
  except OSError:
185
183
  if (time.time() - start_time) > self._timeout:
186
- raise DirLockError(f"could not create {self._lockfilename} after {self._timeout} seconds")
184
+ raise DirLockError(f"Could not create {self._lockfilename} after {self._timeout} seconds")
187
185
  else:
188
186
  time.sleep(self._SPIN_PERIOD_SECONDS)
189
187
 
@@ -0,0 +1,89 @@
1
+
2
+
3
+ {% macro vcf_check_report(vcf_check_result_per_file, vcf_file_names) -%}
4
+ {% for file_name in vcf_file_names %}
5
+ {% set vcf_check_result = vcf_check_result_per_file.get(file_name, {}) %}
6
+ {% set critical_count = vcf_check_result.get("critical_count", 0) %}
7
+ {% set error_count = vcf_check_result.get("error_count", 0) %}
8
+ {% set expand_icon = "" %}
9
+ {% if critical_count > 0 %}
10
+ {% set expand_icon = "&#9654;" %}
11
+ {% set icon = "&#10060;" %}
12
+ {% set row_class = "report-section fail collapsible" %}
13
+ {% elif error_count > 0 %}
14
+ {% set expand_icon = "&#9654;" %}
15
+ {% set icon = "&#10071;" %}
16
+ {% set row_class = "report-section warn collapsible" %}
17
+ {% else %}
18
+ {% set icon = "&#10004;" %}
19
+ {% set row_class = "report-section pass" %}
20
+ {% endif %}
21
+ <div class='{{ row_class }}'><span class="expand_icon">{{ expand_icon }}</span> {{ icon }} {{ file_name }}: {{ critical_count }} critical errors, {{ error_count }} non-critical errors </div>
22
+ {% set critical_list = vcf_check_result.get("critical_list") %}
23
+ {% set error_list = vcf_check_result.get("error_list") %}
24
+
25
+ {% if critical_list or error_list%}
26
+ <div class="error-list">
27
+ <div class="error-description">First 10 errors per category are below. <strong>Full report:</strong> {{ vcf_check_result.get('report_path', '') }}</div>
28
+ <table>
29
+ <tr>
30
+ <th>Category</th><th>Error</th>
31
+ </tr>
32
+ {% for error in critical_list[:10] %}
33
+ <tr>
34
+ <td><strong>critical error</strong></td><td> {{ error }}</td>
35
+ </tr>
36
+ {% endfor %}
37
+ {% for error in error_list[:10] %}
38
+ <tr>
39
+ <td><strong>non-critical error</strong></td><td> {{ error }}</td>
40
+ </tr>
41
+ {% endfor %}
42
+ </table>
43
+ </div>
44
+ {% endif %}
45
+ {% endfor %}
46
+ {%- endmacro %}
47
+
48
+ {% macro assembly_check_report(assembly_check_result_per_file, vcf_file_names) -%}
49
+ {% for file_name in vcf_file_names %}
50
+ {% set assembly_check_result = assembly_check_result_per_file.get(file_name, {}) %}
51
+ {% set nb_match = assembly_check_result.get("match", 0) %}
52
+ {% set nb_total = assembly_check_result.get("total", 0) %}
53
+ {% set match_percentage = nb_match / nb_total * 100 if nb_total else 0 %}
54
+ {% set expand_icon = "" %}
55
+ {% if assembly_check_result.get("nb_mismatch", 0) > 0 or nb_total == 0 %}
56
+ {% set expand_icon = "&#9654;" %}
57
+ {% set icon = "&#10060;" %}
58
+ {% set row_class = "report-section fail collapsible" %}
59
+ {% else %}
60
+ {% set icon = "&#10004;" %}
61
+ {% set row_class = "report-section pass" %}
62
+ {% endif %}
63
+ <div class='{{ row_class }}'><span class="expand_icon">{{ expand_icon }}</span> {{ icon }} {{ file_name }}: {{ nb_match }}/{{ nb_total }} ({{ match_percentage|round(2) }}%)</div>
64
+ {% set mismatch_list = assembly_check_result.get("mismatch_list") %}
65
+ {% set error_list = assembly_check_result.get("error_list") %}
66
+ {% if mismatch_list or error_list %}
67
+ <div class="error-list">
68
+ <div class="error-description">First 10 errors per category are below. <strong>Full report:</strong> {{ assembly_check_result.get('report_path', '') }}</div>
69
+ <table>
70
+ <tr>
71
+ <th>Category</th><th>Error</th>
72
+ </tr>
73
+ {% for error in error_list[:10] %}
74
+ <tr>
75
+ <td><strong>Parsing Error</strong></td><td> {{ error }}</td>
76
+ </tr>
77
+ {% endfor %}
78
+ {% for error in mismatch_list[:10] %}
79
+ <tr>
80
+ <td><strong>mismatch error</strong></td><td> {{ error }}</td>
81
+ </tr>
82
+ {% endfor %}
83
+ </table>
84
+ </div>
85
+ {% endif %}
86
+ {% endfor %}
87
+ {%- endmacro %}
88
+
89
+