OperonDBS 0.8.0__tar.gz → 0.8.2__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.
- {operondbs-0.8.0 → operondbs-0.8.2}/.github/workflows/publish.yml +1 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/.github/workflows/test.yml +9 -8
- {operondbs-0.8.0 → operondbs-0.8.2}/.gitignore +1 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/AGENTS.md +52 -10
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/PKG-INFO +8 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/SOURCES.txt +9 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/PKG-INFO +8 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/README.md +8 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/README_ZH.md +8 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/external-analysis.md +13 -3
- operondbs-0.8.2/docs/en/contributor/defect-tracking.md +71 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/contributor/development-testing.md +32 -22
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/contributor/index.md +2 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/phylogenetics-workflow.md +1 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/qc-profiles.md +6 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/remote-execution.md +3 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/behaviors-and-limitations.md +21 -37
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-analysis.md +7 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-decisions-reports.md +4 -4
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-tui.md +47 -7
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/index.md +2 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/recipe-fields.md +21 -2
- operondbs-0.8.2/docs/en/reference/resolved-issues.md +58 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/external-analysis.md +44 -5
- operondbs-0.8.2/docs/zh/contributor/defect-tracking.md +55 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/contributor/development-testing.md +18 -15
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/contributor/index.md +2 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/phylogenetics-workflow.md +1 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/qc-profiles.md +10 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/remote-execution.md +11 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/behaviors-and-limitations.md +19 -35
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-analysis.md +20 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-decisions-reports.md +13 -8
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-tui.md +38 -7
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/index.md +2 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/recipe-fields.md +30 -3
- operondbs-0.8.2/docs/zh/reference/resolved-issues.md +50 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/adapters/ncbi_datasets.py +13 -10
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/classify.py +36 -14
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/cli.py +15 -4
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/coverage.py +3 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/database.py +51 -37
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/entity_view.py +9 -9
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/environment_capture.py +44 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/execution.py +607 -62
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/export.py +41 -31
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/fanout.py +29 -22
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/files.py +40 -12
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/import_wizard.py +3 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/lifecycle.py +5 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/__init__.py +6 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/release.py +33 -6
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/remotes.py +24 -7
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/rules.py +7 -6
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/sequence_tools.py +2 -2
- operondbs-0.8.2/operon/sql.py +18 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/table_import.py +8 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/taxonomy.py +4 -4
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tools.py +526 -102
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/actions.py +29 -7
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/data.py +38 -15
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/config.py +25 -10
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/files_ops.py +51 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/import_wizard.py +75 -19
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/publish.py +9 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/workflow.py +118 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/pyproject.toml +7 -4
- operondbs-0.8.2/tests/integration/test_analysis_array.py +774 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_analysis_shutdown.py +25 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_classify_sequences.py +45 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_fanout_analyze.py +31 -0
- operondbs-0.8.2/tests/regression/test_sql_identifier_security.py +124 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_classify.py +34 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_core_coverage_more.py +7 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_database_edges_more.py +24 -0
- operondbs-0.8.2/tests/unit/test_defect_registry.py +121 -0
- operondbs-0.8.2/tests/unit/test_defects_cli.py +150 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_environment_capture.py +73 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_execution.py +361 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_execution_edges.py +301 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_export.py +62 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_fanout.py +109 -5
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_files_edges.py +92 -3
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_misc_coverage_more.py +5 -1
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_qc_and_rules.py +37 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_remote_taxonomy_more.py +5 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_remotes.py +2 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tools_execution_more.py +4 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_config.py +93 -14
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_publish.py +197 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_screens_more.py +2 -2
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_writes.py +76 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_views_release_reports_edges.py +60 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/.readthedocs.yaml +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/LICENSE +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/MANIFEST.in +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/dependency_links.txt +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/entry_points.txt +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/requires.txt +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/OperonDBS.egg-info/top_level.txt +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/benchmarks/qc_representative_entities.tsv +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/_static/language-switcher.js +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/_static/operon.css +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/_templates/layout.html +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/conf.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/extensibility.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/files-and-storage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/metadata-and-data-model.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/qc-and-rules.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/release-lifecycle.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/architecture/taxonomy-coverage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/contributor/documentation-deployment.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/contributor/pypi-release.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/contributor/repository-guide.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/getting-started/daily-workflow.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/getting-started/first-project.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/getting-started/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/getting-started/installation.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/getting-started/quickstart.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/backup-migration.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/curation-lifecycle.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/external-analysis.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/file-archiving.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/metadata-import.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/ncbi-datasets.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/remote-first.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/remote-storage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/taxonomy-coverage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/guides/troubleshooting.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/operations/database-compatibility.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/operations/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/operations/ncbi-recovery-migration.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/operations/qc-performance.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-files-qc.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-project-metadata.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-remote.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-taxonomy-lifecycle-admin.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/cli-workflow.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/data-model.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/recipe-overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/en/reference/recipe-parsers-examples.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/requirements.txt +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/extensibility.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/files-and-storage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/metadata-and-data-model.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/qc-and-rules.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/release-lifecycle.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/architecture/taxonomy-coverage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/contributor/documentation-deployment.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/contributor/pypi-release.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/contributor/repository-guide.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/getting-started/daily-workflow.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/getting-started/first-project.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/getting-started/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/getting-started/installation.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/getting-started/quickstart.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/backup-migration.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/curation-lifecycle.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/external-analysis.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/file-archiving.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/metadata-import.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/ncbi-datasets.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/remote-first.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/remote-storage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/taxonomy-coverage.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/guides/troubleshooting.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/operations/database-compatibility.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/operations/index.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/operations/ncbi-recovery-migration.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/operations/qc-performance.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-files-qc.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-project-metadata.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-remote.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-taxonomy-lifecycle-admin.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/cli-workflow.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/data-model.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/recipe-overview.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/docs/zh/reference/recipe-parsers-examples.md +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/__main__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/adapters/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/adapters/timetree.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/backup.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/config.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/demo.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/environment.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/errors.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/lineage.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/metadata_files.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/ncbi_reconcile.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/profiles.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/_alignment.pyx +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/_parsers.pyx +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/alignment.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/measure.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/qc/parsers.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/reports.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/schema.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/shutdown.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/timetree.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/app.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/app.tcss +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/assets/splash.png +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/assets/splash.rgb.z +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/common.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/coverage.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/decisions.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/entities.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/files.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/home.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/screens/runs.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/splash.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/tui/splash_terminal.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/operon/utils.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/setup.cfg +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/setup.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/compatibility/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/compatibility/test_python_support.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/helpers.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_analysis_resume.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_analysis_tools.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_execution_backends.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_lineage_cascade.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_ncbi_datasets_adapter.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_pipeline_and_release.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_python_packaging.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_qc_remote_measure.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/integration/test_taxonomy_coverage.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/regression/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/regression/test_correctness.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/regression/test_cython_alignment_parity.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/regression/test_cython_parser_parity.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/regression/test_parser_semantics.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/__init__.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_alignment_qc.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_cli_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_config_workflow_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_coverage_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_docs_versions.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_environment.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_follow.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_import_backup_show.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_import_wizard_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_lifecycle.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_lineage.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_ncbi_coverage_gaps.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_ncbi_edge_cases.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_ncbi_reconcile_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_parser_edge_paths.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_qc_edges_more.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_qc_measure.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_qc_remote_only.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_recipe_history.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_remote_transport_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_remotes_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_rules_schema_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_schema_2_10.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_schema_2_11.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_schema_2_9.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_schema_and_metadata.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_sequence_tools.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_sequences.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_shutdown.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_support_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_table_import_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_taxonomy_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_timetree.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_timetree_snapshots.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tools_edges.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_flows_more.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_tui_splash_terminal.py +0 -0
- {operondbs-0.8.0 → operondbs-0.8.2}/tests/unit/test_workflow_cli.py +0 -0
|
@@ -71,7 +71,7 @@ jobs:
|
|
|
71
71
|
- run: python -m cibuildwheel --output-dir wheelhouse
|
|
72
72
|
env:
|
|
73
73
|
CIBW_ARCHS: ${{ matrix.architecture }}
|
|
74
|
-
CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-* cp314-*"
|
|
74
|
+
CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-* cp314-* cp315-*"
|
|
75
75
|
CIBW_SKIP: "*-musllinux_*"
|
|
76
76
|
CIBW_TEST_COMMAND: >-
|
|
77
77
|
python -c "import operon; import operon.qc._parsers;
|
|
@@ -32,20 +32,21 @@ jobs:
|
|
|
32
32
|
fail-fast: false
|
|
33
33
|
matrix:
|
|
34
34
|
os: [ ubuntu-latest, macos-latest ]
|
|
35
|
-
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
35
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15"]
|
|
36
36
|
runs-on: ${{ matrix.os }}
|
|
37
37
|
steps:
|
|
38
38
|
- uses: actions/checkout@v6
|
|
39
39
|
- uses: actions/setup-python@v7
|
|
40
40
|
with:
|
|
41
|
+
allow-prereleases: true
|
|
42
|
+
check-latest: true
|
|
41
43
|
python-version: ${{ matrix.python-version }}
|
|
42
44
|
cache: pip
|
|
43
45
|
cache-dependency-path: pyproject.toml
|
|
44
|
-
- run:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
- run: |
|
|
47
|
+
python -m pip install --upgrade pip
|
|
48
|
+
python -m pip install -e '.[test]'
|
|
49
|
+
python -m pytest
|
|
50
|
+
- uses: codacy/codacy-coverage-reporter-action@v1.3.0
|
|
49
51
|
with:
|
|
50
|
-
token: ${{ secrets.
|
|
51
|
-
report_type: test_results
|
|
52
|
+
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
|
@@ -26,7 +26,7 @@ principle-to-implementation mapping.
|
|
|
26
26
|
|
|
27
27
|
Current version markers (must stay consistent across code and docs):
|
|
28
28
|
|
|
29
|
-
- `operon` 0.8.
|
|
29
|
+
- `operon` 0.8.2 (`pyproject.toml`)
|
|
30
30
|
- database schema 2.11 (`operon/database.py`, `SCHEMA_VERSION`)
|
|
31
31
|
- metadata schema 1.4 (`operon/schema.py`, `METADATA_SCHEMA_VERSION`)
|
|
32
32
|
|
|
@@ -133,7 +133,9 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
133
133
|
(see `docs/*/operations/qc-performance.md`).
|
|
134
134
|
- `scripts/` — local developer tooling; `setup-test-matrix.sh` and
|
|
135
135
|
`run-test-matrix.sh` build and drive the uv-managed Python 3.10–3.14
|
|
136
|
-
matrix under .matrix/ (see `docs/*/contributor/development-testing.md`)
|
|
136
|
+
matrix under .matrix/ (see `docs/*/contributor/development-testing.md`);
|
|
137
|
+
`defects.sh` appends to and queries the defect registry (`defects.yml`,
|
|
138
|
+
see "Defect reports" below).
|
|
137
139
|
|
|
138
140
|
## Setup, test, and build
|
|
139
141
|
|
|
@@ -152,7 +154,7 @@ python -m pytest tests/unit # by category: unit / integration /
|
|
|
152
154
|
|
|
153
155
|
python -m pytest --lf -q --no-cov # iterate: last failures, no coverage
|
|
154
156
|
python -m pytest -n 4 --dist loadfile # parallel full suite (xdist, in the dev/test extras)
|
|
155
|
-
scripts/run-test-matrix.sh # whole suite on 3.10-3.
|
|
157
|
+
scripts/run-test-matrix.sh # whole suite on 3.10-3.15 concurrently
|
|
156
158
|
|
|
157
159
|
python setup.py build_ext --inplace # rebuild only the Cython extension
|
|
158
160
|
|
|
@@ -160,12 +162,33 @@ sphinx-build -W --keep-going -b html docs docs/_build/html # strict docs build
|
|
|
160
162
|
```
|
|
161
163
|
|
|
162
164
|
Run the relevant test category after any change; run the full suite before
|
|
163
|
-
considering work done.
|
|
164
|
-
Python 3.10–3.14 and the strict Sphinx build. Releases are published
|
|
165
|
-
exclusively to PyPI; see `docs/*/contributor/pypi-release.md`.
|
|
165
|
+
considering work done.
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
CI (`.github/workflows/test.yml`) runs pytest on Python 3.10–3.15 and the strict
|
|
168
|
+
Sphinx build. Releases are published exclusively to PyPI; see `docs/*/contributor/pypi-release.md`.
|
|
169
|
+
|
|
170
|
+
The project uses `pytest-xdist` to parallel testing. Avoid sharing state between tests
|
|
171
|
+
to prevent unexpected or random test results.
|
|
172
|
+
|
|
173
|
+
> Running `python -m pytest` directly takes approx 35 seconds
|
|
174
|
+
> (auto: 24 workers). Running the local test matrix takes 3 minutes
|
|
175
|
+
> (6 jobs × 4 workers), or 4~5min (6 jobs × 2 workers in default).
|
|
176
|
+
>
|
|
177
|
+
> Measured on Intel Core i7-13700HX (16c24t).
|
|
178
|
+
|
|
179
|
+
## Git
|
|
180
|
+
|
|
181
|
+
If the user requests or grants permission, do `git commit` after modify.
|
|
182
|
+
Avoid including overly large changes in a single commit. For commit messages,
|
|
183
|
+
follow the pattern used in the last five commits; otherwise, the Conventional
|
|
184
|
+
Commits guidelines.
|
|
185
|
+
|
|
186
|
+
**DO NOT** push any commit or tag unless the user **explicitly** requests that.
|
|
187
|
+
|
|
188
|
+
If times out, assume the user is not present and that a GPG signature
|
|
189
|
+
is required. Add `-c commit.gpgsign=false` behind `git` may help (However,
|
|
190
|
+
re-signing will reset the commit hash, and corrupt the defects.yml. Please
|
|
191
|
+
proceed with caution).
|
|
169
192
|
|
|
170
193
|
## Conventions
|
|
171
194
|
|
|
@@ -203,6 +226,22 @@ asks.
|
|
|
203
226
|
and an F821 error is likely to occur. Globally ignoring F821 is **STRICKLY
|
|
204
227
|
PROHIBITED**.
|
|
205
228
|
|
|
229
|
+
## Defect reports
|
|
230
|
+
|
|
231
|
+
Confirmed defects are tracked in the machine-readable registry
|
|
232
|
+
`defects.yml` at the repository root (plus any `defects/*.yml` shards;
|
|
233
|
+
`scripts/defects.sh` appends and queries records). The full process is in
|
|
234
|
+
`docs/*/contributor/defect-tracking.md`; the binding rules are:
|
|
235
|
+
|
|
236
|
+
1. **Register first.** When an audit or investigation confirms a defect,
|
|
237
|
+
append its `ODR-XXXX` record to `defects.yml` before the fix lands.
|
|
238
|
+
2. **One commit per defect.** The fix and its regression tests ride in the
|
|
239
|
+
same commit; fill in `fix_commit` when committing.
|
|
240
|
+
3. **Close the test loop.** Regression tests for a defect carry
|
|
241
|
+
`@pytest.mark.bug("ODR-XXXX")`, and every `fixed`/`verified` record
|
|
242
|
+
lists at least one such test; `tests/unit/test_defect_registry.py`
|
|
243
|
+
validates the registry schema and both directions of this closure.
|
|
244
|
+
|
|
206
245
|
## Documentation sync
|
|
207
246
|
|
|
208
247
|
When you change behavior, CLI surface, configuration fields, or storage
|
|
@@ -218,7 +257,7 @@ change:
|
|
|
218
257
|
- Contributor-facing processes → `docs/*/contributor/`; navigation →
|
|
219
258
|
`docs/*/index.md`
|
|
220
259
|
|
|
221
|
-
Version markers in docs (`operon` 0.8.
|
|
260
|
+
Version markers in docs (`operon` 0.8.2, database schema 2.11, metadata
|
|
222
261
|
schema 1.4) must match `pyproject.toml` and the code. Do not write the
|
|
223
262
|
current values literally in Markdown sources: use the `myst_substitutions`
|
|
224
263
|
references `{{ operon_version }}`, `{{ db_schema }}`, and
|
|
@@ -235,6 +274,9 @@ Sphinx-rendered); update the list above when bumping.
|
|
|
235
274
|
|
|
236
275
|
## Special Note For Codex/ChatGPT
|
|
237
276
|
|
|
238
|
-
Due to specific limitations of the sandbox environment, executing certain TUI
|
|
277
|
+
Due to specific limitations of the sandbox environment, executing certain TUI
|
|
278
|
+
test code may cause the system to freeze; this often occurs on Codex/ChatGPT.
|
|
279
|
+
The specific reason is that when this test code runs in the sandbox, it may
|
|
280
|
+
result a Textual/asyncio cleanup block, and reports "FAIL" due to timeout.
|
|
239
281
|
|
|
240
282
|
If you are Codex/ChatGPT, please execute TUI-related test code OUTSIDE the sandbox.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OperonDBS
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Operon the Database System: Archive, Quality-Control, Organize, Analyze and Release Your Bio-Data
|
|
5
5
|
Author-email: hyli360 <lihuanyu2003@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -46,9 +46,14 @@ Requires-Dist: myst-parser<5,>=4.0; extra == "dev"
|
|
|
46
46
|
Requires-Dist: sphinx-rtd-theme<4,>=3.0; extra == "dev"
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
49
|
-
# Operon
|
|
49
|
+
# Operon the Database System
|
|
50
50
|
|
|
51
|
-
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
51
|
+
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
52
|
+
[](https://operonproject.readthedocs.io/)
|
|
53
|
+

|
|
54
|
+

|
|
55
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
56
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
|
|
52
57
|
|
|
53
58
|
A Python-based, **file-based database** designed for large-scale genomic data, used for archiving, quality control, analysis, and deterministic automation.
|
|
54
59
|
|
|
@@ -33,6 +33,7 @@ docs/en/architecture/overview.md
|
|
|
33
33
|
docs/en/architecture/qc-and-rules.md
|
|
34
34
|
docs/en/architecture/release-lifecycle.md
|
|
35
35
|
docs/en/architecture/taxonomy-coverage.md
|
|
36
|
+
docs/en/contributor/defect-tracking.md
|
|
36
37
|
docs/en/contributor/development-testing.md
|
|
37
38
|
docs/en/contributor/documentation-deployment.md
|
|
38
39
|
docs/en/contributor/index.md
|
|
@@ -75,6 +76,7 @@ docs/en/reference/index.md
|
|
|
75
76
|
docs/en/reference/recipe-fields.md
|
|
76
77
|
docs/en/reference/recipe-overview.md
|
|
77
78
|
docs/en/reference/recipe-parsers-examples.md
|
|
79
|
+
docs/en/reference/resolved-issues.md
|
|
78
80
|
docs/zh/index.md
|
|
79
81
|
docs/zh/overview.md
|
|
80
82
|
docs/zh/architecture/extensibility.md
|
|
@@ -86,6 +88,7 @@ docs/zh/architecture/overview.md
|
|
|
86
88
|
docs/zh/architecture/qc-and-rules.md
|
|
87
89
|
docs/zh/architecture/release-lifecycle.md
|
|
88
90
|
docs/zh/architecture/taxonomy-coverage.md
|
|
91
|
+
docs/zh/contributor/defect-tracking.md
|
|
89
92
|
docs/zh/contributor/development-testing.md
|
|
90
93
|
docs/zh/contributor/documentation-deployment.md
|
|
91
94
|
docs/zh/contributor/index.md
|
|
@@ -128,6 +131,7 @@ docs/zh/reference/index.md
|
|
|
128
131
|
docs/zh/reference/recipe-fields.md
|
|
129
132
|
docs/zh/reference/recipe-overview.md
|
|
130
133
|
docs/zh/reference/recipe-parsers-examples.md
|
|
134
|
+
docs/zh/reference/resolved-issues.md
|
|
131
135
|
operon/__init__.py
|
|
132
136
|
operon/__main__.py
|
|
133
137
|
operon/backup.py
|
|
@@ -158,6 +162,7 @@ operon/rules.py
|
|
|
158
162
|
operon/schema.py
|
|
159
163
|
operon/sequence_tools.py
|
|
160
164
|
operon/shutdown.py
|
|
165
|
+
operon/sql.py
|
|
161
166
|
operon/table_import.py
|
|
162
167
|
operon/taxonomy.py
|
|
163
168
|
operon/timetree.py
|
|
@@ -199,6 +204,7 @@ tests/helpers.py
|
|
|
199
204
|
tests/compatibility/__init__.py
|
|
200
205
|
tests/compatibility/test_python_support.py
|
|
201
206
|
tests/integration/__init__.py
|
|
207
|
+
tests/integration/test_analysis_array.py
|
|
202
208
|
tests/integration/test_analysis_resume.py
|
|
203
209
|
tests/integration/test_analysis_shutdown.py
|
|
204
210
|
tests/integration/test_analysis_tools.py
|
|
@@ -216,6 +222,7 @@ tests/regression/test_correctness.py
|
|
|
216
222
|
tests/regression/test_cython_alignment_parity.py
|
|
217
223
|
tests/regression/test_cython_parser_parity.py
|
|
218
224
|
tests/regression/test_parser_semantics.py
|
|
225
|
+
tests/regression/test_sql_identifier_security.py
|
|
219
226
|
tests/unit/__init__.py
|
|
220
227
|
tests/unit/test_alignment_qc.py
|
|
221
228
|
tests/unit/test_classify.py
|
|
@@ -224,6 +231,8 @@ tests/unit/test_config_workflow_edges.py
|
|
|
224
231
|
tests/unit/test_core_coverage_more.py
|
|
225
232
|
tests/unit/test_coverage_edges.py
|
|
226
233
|
tests/unit/test_database_edges_more.py
|
|
234
|
+
tests/unit/test_defect_registry.py
|
|
235
|
+
tests/unit/test_defects_cli.py
|
|
227
236
|
tests/unit/test_docs_versions.py
|
|
228
237
|
tests/unit/test_environment.py
|
|
229
238
|
tests/unit/test_environment_capture.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OperonDBS
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.2
|
|
4
4
|
Summary: Operon the Database System: Archive, Quality-Control, Organize, Analyze and Release Your Bio-Data
|
|
5
5
|
Author-email: hyli360 <lihuanyu2003@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -46,9 +46,14 @@ Requires-Dist: myst-parser<5,>=4.0; extra == "dev"
|
|
|
46
46
|
Requires-Dist: sphinx-rtd-theme<4,>=3.0; extra == "dev"
|
|
47
47
|
Dynamic: license-file
|
|
48
48
|
|
|
49
|
-
# Operon
|
|
49
|
+
# Operon the Database System
|
|
50
50
|
|
|
51
|
-
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
51
|
+
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
52
|
+
[](https://operonproject.readthedocs.io/)
|
|
53
|
+

|
|
54
|
+

|
|
55
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
56
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
|
|
52
57
|
|
|
53
58
|
A Python-based, **file-based database** designed for large-scale genomic data, used for archiving, quality control, analysis, and deterministic automation.
|
|
54
59
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
# Operon
|
|
2
|
-
|
|
3
|
-
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
1
|
+
# Operon the Database System
|
|
2
|
+
|
|
3
|
+
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
4
|
+
[](https://operonproject.readthedocs.io/)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
8
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
|
|
4
9
|
|
|
5
10
|
A Python-based, **file-based database** designed for large-scale genomic data, used for archiving, quality control, analysis, and deterministic automation.
|
|
6
11
|
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
# Operon
|
|
2
|
-
|
|
3
|
-
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
1
|
+
# Operon the Database System
|
|
2
|
+
|
|
3
|
+
[](https://github.com/HYLi360/Operon/actions/workflows/test.yml)
|
|
4
|
+
[](https://operonproject.readthedocs.io/)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
8
|
+
[](https://app.codacy.com/gh/HYLi360/Operon/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
|
|
4
9
|
|
|
5
10
|
一个基于 Python 的、面向大规模基因组数据的**基于文件的数据库**,用于归档、质控、分析与确定性自动化处理。
|
|
6
11
|
|
|
@@ -20,13 +20,13 @@ Actual execution of external commands is taken over by the backend abstraction i
|
|
|
20
20
|
|
|
21
21
|
- `local` (default): the original local subprocess behavior, completely unchanged;
|
|
22
22
|
- `slurm`: a local Slurm cluster. Generates a `<run_id>.sbatch` batch script under `logs/` (`--cpus-per-task` takes the thread count; optional `--time`/`--partition`/`--mem`, `extra_sbatch`, and `setup_commands`), submits with `sbatch --parsable`, polls `squeue` at `poll_interval`, and after the job disappears reads the `<run_id>.exitcode` file written by the script (falling back to `sacct` on failure); requires the project directory to be on a filesystem shared with the compute nodes;
|
|
23
|
-
- `ssh`: executes on an SSH remote host (HPC head node / cloud VM) through the lazily imported Paramiko runtime dependency; with `execution.ssh.scheduler: slurm`, sbatch/squeue runs on the remote instead. Supports `remote_root` path mapping (empty means a shared filesystem); input files are uploaded over SFTP (identical content skipped, strict SHA-256/directory-tree hash, different content refused). When `storage_remote` is configured, REMOTE_ONLY inputs are consumed in place on the remote. Before a run,
|
|
23
|
+
- `ssh`: executes on an SSH remote host (HPC head node / cloud VM) through the lazily imported Paramiko runtime dependency; with `execution.ssh.scheduler: slurm`, sbatch/squeue runs on the remote instead. Supports `remote_root` path mapping (empty means a shared filesystem); input files are uploaded over SFTP (identical content skipped, strict SHA-256/directory-tree hash, different content refused). When `storage_remote` is configured, REMOTE_ONLY inputs are consumed in place on the remote. Before a run, an existing remote output is renamed to a `<path>.operon-prev-<uuid>` backup rather than deleted; the backup is dropped once the run succeeds and the new output verifies, and a failed or interrupted run best-effort restores it in place. Expected outputs are pulled back through temporary files and compared against the remote content again; an existing local output is accepted only when its content is identical. `storage_remote` and an explicit `remote_root` must point to the same root. One analysis batch uses a single lazy SSH client for version probing, remote input verification, database preflight, and all commands, closing it uniformly at the end. Direct commands run in a separate process group via util-linux `setsid --wait` (guaranteeing reliable exit-code return); on timeout, TERM/KILL is sent to the remote process group based on a restricted PID file, and when a termination request cannot be sent, the error and provenance state explicitly that the process may still be running. Remote Slurm polls strictly at `poll_interval` and retries the exitcode file that is briefly invisible after a job disappears.
|
|
24
24
|
|
|
25
25
|
All three backends share the same provenance and correctness contract: exit codes, start/end times, and logs are written to `workflow_runs` and `logs/workflow.jsonl` as usual; SQLite additionally stores the executor, scheduler job ID, and resource/script details; success determination and input/output SHA-256 verification are unchanged; tool version probing on non-`local` backends also goes through the same backend. An individual recipe can override same-named fields of `execution.slurm` with a `slurm:` mapping (e.g. adjusting memory/time for BUSCO alone).
|
|
26
26
|
|
|
27
27
|
Execution environment capture (`environment.py`, `environment_capture.py`) stores normalized JSON in `execution_environments`, addressed by `environment_id`. Runs and analysis jobs reference that document; each command-chain step also records its own environment ID. No database migration is needed for the extended JSON document (`capture_schema: 1`). The document is redacted at capture time, before storage: the hostname is replaced by `sha256:` plus the first 16 hex characters of its SHA-256, and the `$HOME` prefix of path-like values (`PATH`, `CONDA_PREFIX`, `VIRTUAL_ENV`, the conda prefix) is replaced by `~`. Remote probes transfer the raw values (probe files are written with umask 077) and the controlling Python process redacts them before storage; a transient `home` probe key feeds the replacement and is then discarded, never entering the stored document or any fingerprint. The `environment_id` and sub-fingerprints are computed from the redacted document, so identical configurations captured on different hosts deduplicate to one record. Documents recorded before redaction was introduced are content-addressed and immutable and are not migrated; new captures produce new environment IDs.
|
|
28
28
|
|
|
29
|
-
The local, Slurm and SSH backends probe immediately before the payload. Slurm probes after `setup_commands` on the compute node; direct SSH probes in the payload shell's working directory. Recognized `conda`, `mamba` and `micromamba run` launchers run the probe through the same launcher and target name/prefix. Reading `conda-meta/*.json` requires no Python or package-manager CLI inside the target environment. Direct programs inherit the executor environment. Known opaque shell/container launchers and unsupported manager options are labelled `unsupported_launcher`, with `capture_scope: executor_only`; their outer environment is not claimed as the tool's Conda environment. Arbitrary custom wrappers are not introspected.
|
|
29
|
+
The local, Slurm and SSH backends probe immediately before the payload. The local probe is memoized in-process per (launcher, working directory) for 300 seconds (`_LOCAL_CAPTURE_TTL_SECONDS`), so a batch of commands through one launcher pays for one probe; failed captures are not cached. Slurm probes after `setup_commands` on the compute node; direct SSH probes in the payload shell's working directory. Recognized `conda`, `mamba` and `micromamba run` launchers run the probe through the same launcher and target name/prefix. Reading `conda-meta/*.json` requires no Python or package-manager CLI inside the target environment. Direct programs inherit the executor environment. Known opaque shell/container launchers and unsupported manager options are labelled `unsupported_launcher`, with `capture_scope: executor_only`; their outer environment is not claimed as the tool's Conda environment. Arbitrary custom wrappers are not introspected.
|
|
30
30
|
|
|
31
31
|
Conda snapshots retain package name, version, build, subdir, dependencies, archive URL and available SHA-256/MD5. Complete inventories include an `@EXPLICIT` reconstruction specification (SHA-256 preferred, MD5 fallback). Package fingerprints exclude installation prefixes and hostnames. Credential-bearing URL components (userinfo, `/t/` tokens and queries) are removed. Private channels may consequently require credentials supplied separately during restoration. Pip-installed distribution names detected through `INSTALLER` metadata are reported separately; neither pip packages, editable installs, manually modified files nor custom activation scripts are restored by the Conda specification. The package inventory describes original archives, not a verification of installed bytes. Empty, malformed, interrupted or unresolvable inventories cannot be exported as complete specifications.
|
|
32
32
|
|
|
@@ -48,6 +48,16 @@ Whenever a backend cannot collect a metric the column stays NULL — no error is
|
|
|
48
48
|
|
|
49
49
|
`run-external` provenance is aligned with `analyze`: `--tool NAME` matching a tool configured in `config/tools.yaml` triggers automatic version detection recorded as `tool_version` and `tool_version_raw` (a failed probe degrades to a warning and does not block the run); `--input PATH` (repeatable) declares input files whose per-file SHA-256 values are combined into `input_sha256`, with the full list recorded in `execution_details`; `--threads` records the thread count requested from the execution backend.
|
|
50
50
|
|
|
51
|
-
Graceful shutdown (`shutdown.py`): while an `analyze` batch is running, SIGINT/SIGTERM handlers are installed; a signal is converted into `ShutdownRequested` (a `KeyboardInterrupt` subclass) raised on the main thread, and cleanup follows the normal exception path — `local` backend subprocesses start with `start_new_session` in their own process group, and on interruption/timeout the whole process group (including grandchildren) receives TERM then KILL; the `slurm` and remote-Slurm backends `scancel` the current job on interruption; the `ssh` direct backend reuses the timeout path's remote process-group TERM/KILL. The current `analysis_jobs` row is set to `interrupted` (it does not participate in completed-cache hits), half-finished output is deleted by default (`--keep-partial` keeps it), and the batch then terminates with exit code 130; a second signal during cleanup forces an immediate exit. A `RUNNING` row left behind by a SIGKILLed process is swept to `interrupted` at the next `analyze` startup, so resume semantics always hold.
|
|
51
|
+
Graceful shutdown (`shutdown.py`): while an `analyze` batch is running, SIGINT/SIGTERM handlers are installed; a signal is converted into `ShutdownRequested` (a `KeyboardInterrupt` subclass) raised on the main thread, and cleanup follows the normal exception path — `local` backend subprocesses start with `start_new_session` in their own process group, and on interruption/timeout the whole process group (including grandchildren) receives TERM then KILL; the `slurm` and remote-Slurm backends `scancel` the current job on interruption; the `ssh` direct backend reuses the timeout path's remote process-group TERM/KILL. The current `analysis_jobs` row is set to `interrupted` (it does not participate in completed-cache hits), half-finished output is deleted by default (`--keep-partial` keeps it), and the batch then terminates with exit code 130; a second signal during cleanup forces an immediate exit. A `RUNNING` row of the same analysis left behind by a SIGKILLed process is swept to `interrupted` at the next `analyze` startup, so resume semantics always hold.
|
|
52
|
+
|
|
53
|
+
## Slurm array submission
|
|
54
|
+
|
|
55
|
+
On HPC clusters, submitting N files of one recipe as N separate scheduler jobs pays N times the queue and accounting overhead for what is logically one batch. When a recipe opts in (`slurm.array: true`), the selected executor implements array submission, and at least two files of one `analyze` batch miss the cache, `analyze` instead submits them as a single Slurm job array — one `sbatch`, one `squeue` poll loop — with each file occupying one array task. The `local` backend and direct SSH (`scheduler: none`) do not implement array submission, so any unmet condition falls back to the per-file submission path unchanged; for the SSH executor the capability exists only with `scheduler: slurm` (its `run_array` attribute is `None` otherwise).
|
|
56
|
+
|
|
57
|
+
The mechanism mirrors the per-file path. `run_array` writes a tab-separated manifest (`logs/<batch_id>.array-manifest.tsv`) with one line per task — index, run_id, stdout/stderr/exitcode/probe paths, and the rendered command as the last field — and renders one array script (`render_slurm_array_script`) that dispatches line N to array task N via `sed -n "${SLURM_ARRAY_TASK_ID}p"`. The SBATCH header, `setup_commands`, the `cd` guard, the per-task environment probe, and the self-written exit-code file are shared with the single-job script; `slurm.array_concurrency: N` becomes the `%N` throttle on `--array=1-M%N`. Each task keeps its own `logs/<run_id>.*` files, so per-file provenance granularity is unchanged: every file still gets its own `workflow_runs` row, with `scheduler_job_id` recorded as `<array_id>_<task_index>` and the array id kept in the run details as `array_job_id`. Accounting is queried per task (`sacct -j <array_id>_<index>`), so the sacct signal-folding semantics (an OOM kill's `0:9` becomes 137) apply per task exactly as for single jobs. Through the SSH executor with a remote Slurm scheduler the same flow runs remotely: manifest, probe scripts, and array script are staged over SFTP, `sbatch`/`squeue` run on the remote host, and per-task logs, exit codes, and sacct accounting are pulled back.
|
|
58
|
+
|
|
59
|
+
Array participation is a submission strategy, not an environment or parameter difference, so it never enters the parameter fingerprint or cache identity: a recipe shares the same completed cache with array submission on or off, and cache hits work identically either way. Because candidate order is deterministic and the manifest carries each task's rendered command, the task-to-file mapping is auditable and immune to resume/`--limit` drift.
|
|
60
|
+
|
|
61
|
+
Interrupt bookkeeping contract: on KeyboardInterrupt the whole array is cancelled once with `scancel` and the exception propagates; the caller distinguishes finished tasks by which per-task `<run_id>.exitcode` files exist (the remote path pulls back any exit-code files that already exist before re-raising, so the same check works against local paths). Tasks without an exit-code file are marked `interrupted` — they never pollute the completed cache — and their partial outputs are removed under the usual per-file semantics (`--keep-partial` keeps them), so re-running the same command resumes exactly the unfinished files.
|
|
52
62
|
|
|
53
63
|
For day-to-day use, see the [how-to guides](../guides/index.md); for the full contract of fields, placeholders, artifacts, database identity, caching, and parsers, see the [recipe configuration reference](../reference/recipe-overview.md).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Defect tracking
|
|
2
|
+
|
|
3
|
+
The current defect tracking of Operon records the confirmed defects in
|
|
4
|
+
a machine-readable registry: `defects.yml` at the repository root,
|
|
5
|
+
instead of external issue tracker. The registry is the single source
|
|
6
|
+
of truth for defect reports and their disposition; [Resolved issues](../reference/resolved-issues.md)
|
|
7
|
+
is the user-facing summary and keeps the historical K-series numbers
|
|
8
|
+
alongside the ODR series.
|
|
9
|
+
|
|
10
|
+
> K-series numbers are archived only in [Resolved Issues](../reference/resolved-issues.md).
|
|
11
|
+
> The registry will not be updated with, or supplemented by K-series numbers.
|
|
12
|
+
|
|
13
|
+
## Registry
|
|
14
|
+
|
|
15
|
+
Every confirmed defect gets one record under `defects:` with a sequential
|
|
16
|
+
`ODR-XXXX` id. Records load from `defects.yml` plus any `defects/*.yml`
|
|
17
|
+
shards (sorted by name), so an overgrown registry can be split without
|
|
18
|
+
changing tooling.
|
|
19
|
+
|
|
20
|
+
Record fields:
|
|
21
|
+
|
|
22
|
+
| Field | Content |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `id` | `ODR-XXXX`, sequential, unique (validated) |
|
|
25
|
+
| `title` | one-line summary |
|
|
26
|
+
| `reported` | ISO date the defect was confirmed |
|
|
27
|
+
| `introduced_in` | version or commit that introduced the defect, or `null` if undetermined |
|
|
28
|
+
| `affected` | affected versions and the preconditions for triggering |
|
|
29
|
+
| `severity` | `low` / `medium` / `high` / `critical` |
|
|
30
|
+
| `component` | primary module or subsystem |
|
|
31
|
+
| `status` | `open` → `confirmed` → `fixed` → `verified`; `wontfix` / `duplicate` are terminal |
|
|
32
|
+
| `reproduction` | observed behavior and how it was reproduced |
|
|
33
|
+
| `disposition` | what was done (or why no action) |
|
|
34
|
+
| `fix_commit` | 40-hex commit id once the fix lands; `null` while pending (format-validated only) |
|
|
35
|
+
| `fixed_in` | release version once shipped; `null` until then |
|
|
36
|
+
| `regression_tests` | `path::test` list; mandatory for `fixed`/`verified` |
|
|
37
|
+
|
|
38
|
+
Use `scripts/defects.sh` to append and query records:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
scripts/defects.sh list [--status open] [--component tools]
|
|
42
|
+
scripts/defects.sh show ODR-0001
|
|
43
|
+
scripts/defects.sh add --title "..." --severity medium --component tools \
|
|
44
|
+
--reproduction "..."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The shell script is a small launcher for `scripts/defects.py`; it selects the
|
|
48
|
+
project virtual environment when available. `list` uses a table on wide
|
|
49
|
+
terminals and a compact per-record layout on narrow terminals. `show` formats
|
|
50
|
+
long record fields as wrapped sections. Colors are enabled only for an
|
|
51
|
+
interactive terminal and can be disabled with `NO_COLOR`.
|
|
52
|
+
|
|
53
|
+
`add` allocates the next id and appends a `status: open` record. It keeps the
|
|
54
|
+
existing registry schema and YAML storage format unchanged.
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
|
|
58
|
+
1. **Register first.** When an audit or investigation confirms a defect,
|
|
59
|
+
append its record to `defects.yml` before the fix lands.
|
|
60
|
+
2. **One commit per defect.** The fix and its regression tests ride in the
|
|
61
|
+
same commit; fill in `fix_commit` when committing.
|
|
62
|
+
3. **Close the test loop.** Every regression test for a defect carries
|
|
63
|
+
`@pytest.mark.bug("ODR-XXXX")` (registered in `pyproject.toml`), and
|
|
64
|
+
every `fixed`/`verified` record lists at least one such test.
|
|
65
|
+
`tests/unit/test_defect_registry.py` validates the registry schema and
|
|
66
|
+
both directions of the marker closure, so a missing record, a dangling
|
|
67
|
+
marker, or a `fixed` record without a regression test fails the suite.
|
|
68
|
+
`python -m pytest -m bug` runs exactly the defect regressions.
|
|
69
|
+
|
|
70
|
+
`verified` additionally requires `fix_commit` and `fixed_in`, and is set
|
|
71
|
+
when the fix ships in a release.
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## Setup and test runs
|
|
4
4
|
|
|
5
|
-
Install the repository checkout with the `dev` extra as described in [Installation](../getting-started/installation.md#install-from-the-repository); it adds pytest, Cython, and
|
|
5
|
+
Install the repository checkout with the `dev` extra as described in [Installation](../getting-started/installation.md#install-from-the-repository); it adds pytest, Cython, and
|
|
6
|
+
Sphinx. Then:
|
|
6
7
|
|
|
7
8
|
```bash
|
|
8
9
|
python -m pytest
|
|
@@ -16,36 +17,44 @@ python -m pytest tests/regression tests/compatibility
|
|
|
16
17
|
sphinx-build -W --keep-going -b html docs docs/_build/html
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
The pytest suite is organized into four categories — `unit`, `integration`, `regression`, `compatibility` — covering:
|
|
20
|
-
|
|
20
|
+
The pytest suite is organized into four categories — `unit`, `integration`, `regression`, `compatibility` — covering:
|
|
21
|
+
Python 3.10 syntax and runtime gates, schema validation and controlled vocabularies, metadata round-trips and
|
|
22
|
+
transaction rollback, stable IDs, default copy isolation, query read-only constraints, file-aware QC identity,
|
|
23
|
+
profile/decision history, gzip FASTA recognition, assembly/annotation QC, rule decisions, idempotent ingest and conflict
|
|
24
|
+
protection, checksum-tamper detection, the demo end-to-end pipeline and release verification, the NCBI Datasets adapter,
|
|
25
|
+
wrapped BLAST/HMMER/BUSCO execution, directory artifacts, JSON summaries, conda run prefix parsing, cache hits/forced
|
|
26
|
+
re-runs, result write-back, and input-tamper rejection.
|
|
27
|
+
The taxonomy coverage integration tests additionally cover taxonomy source-package identity conflicts, profile
|
|
28
|
+
type/content conflicts, exclusion rules, secondary TaxIDs, denominator/report idempotence, and that active metadata
|
|
29
|
+
modifications do not affect the release-frozen scope.
|
|
30
|
+
|
|
31
|
+
The project uses `pytest-xdist` to parallel testing. Avoid sharing state between tests to prevent unexpected or random
|
|
32
|
+
test results.
|
|
21
33
|
|
|
22
34
|
## Fast local verification
|
|
23
35
|
|
|
24
|
-
The full suite takes about seven minutes serially; the loop below aims to run it at most
|
|
25
|
-
once per change.
|
|
36
|
+
The full suite takes about seven minutes serially; the loop below aims to run it at most once per change.
|
|
26
37
|
|
|
27
38
|
1. **Re-run only what failed.** `python -m pytest --lf -q --no-cov` replays pytest's
|
|
28
39
|
last-failed cache before anything else.
|
|
29
40
|
2. **Stop at the first failure** while iterating: `python -m pytest tests/unit -x -q --no-cov`,
|
|
30
41
|
with the file or test you actually touched rather than a whole category.
|
|
31
|
-
3. **
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
CPython 3.10-3.13 interpreters plus one venv per version inside `.matrix/` (3.14 comes
|
|
38
|
-
from the project `.venv`), and `scripts/run-test-matrix.sh` runs all five concurrently:
|
|
42
|
+
3. **Parallel execution.** On a 24-core workstation, running `python -m pytest -n 24 --dist loadfile`
|
|
43
|
+
(with `pytest-xdist`) can reduce the execution time to 30–40 seconds. `--dist loadfile` ensures that each test file
|
|
44
|
+
is assigned to only one worker, which is required for Textual UI testing.
|
|
45
|
+
Coverages are the most resource-intensive: use `--no-cov` during iterations and run the test only once at the end.
|
|
46
|
+
4. **Cross-version matrix in one pass.** `scripts/setup-test-matrix.sh` creates uv-managed CPython 3.10-3.15
|
|
47
|
+
interpreters plus one venv per version inside `.matrix/`. `scripts/run-test-matrix.sh` runs all six concurrently:
|
|
39
48
|
|
|
40
49
|
```bash
|
|
41
50
|
scripts/setup-test-matrix.sh # once per machine
|
|
42
|
-
scripts/run-test-matrix.sh # whole suite,
|
|
51
|
+
scripts/run-test-matrix.sh # whole suite, six versions, 2~3 minutes
|
|
43
52
|
scripts/run-test-matrix.sh tests/unit -x # extra pytest arguments are forwarded
|
|
44
|
-
MATRIX_JOBS=
|
|
53
|
+
MATRIX_JOBS=4 scripts/run-test-matrix.sh # workers per version
|
|
45
54
|
```
|
|
46
55
|
|
|
47
56
|
Each version logs to `.matrix/logs/<version>.log`, so a failure there can be re-run
|
|
48
|
-
directly with that interpreter. The scripts work on Linux and macOS
|
|
57
|
+
directly with that interpreter. The scripts work on Linux and macOS. `.matrix/` is
|
|
49
58
|
git-ignored.
|
|
50
59
|
5. **Platform-specific code cannot be verified by one matrix job alone.** Linux and macOS
|
|
51
60
|
differ in the system utilities the environment probe calls and in `pathlib`/`resource`
|
|
@@ -53,14 +62,12 @@ once per change.
|
|
|
53
62
|
should carry a test that reproduces the other platform's condition on Linux — for
|
|
54
63
|
example an empty `PATH` without GNU `timeout` — rather than depending on the macOS job
|
|
55
64
|
to notice.
|
|
56
|
-
6. **CI runs the matrix in parallel.** The strict documentation build is its own small
|
|
57
|
-
job, and the ten-job matrix (two workers per job, so a four-core runner is not
|
|
58
|
-
oversubscribed) starts immediately; use the local ladder above when you want a faster
|
|
59
|
-
verdict than the matrix can give.
|
|
60
65
|
|
|
61
66
|
## Special Note For Codex/ChatGPT
|
|
62
67
|
|
|
63
|
-
Due to specific limitations of the sandbox environment, executing certain TUI test code may cause the system to freeze;
|
|
68
|
+
Due to specific limitations of the sandbox environment, executing certain TUI test code may cause the system to freeze;
|
|
69
|
+
this often occurs on Codex/ChatGPT. The specific reason is that when this test code runs in the sandbox, it may result
|
|
70
|
+
a Textual/asyncio cleanup block, and reports "FAIL" due to timeout.
|
|
64
71
|
|
|
65
72
|
If you are Codex/ChatGPT, please execute TUI-related test code OUTSIDE the sandbox.
|
|
66
73
|
|
|
@@ -68,7 +75,10 @@ This information has also been updated in AGENTS.md.
|
|
|
68
75
|
|
|
69
76
|
## Coverage gate
|
|
70
77
|
|
|
71
|
-
`python -m pytest` always measures coverage (`--cov=operon --cov-branch`, configured in `pyproject.toml`) and fails when
|
|
78
|
+
`python -m pytest` always measures coverage (`--cov=operon --cov-branch`, configured in `pyproject.toml`) and fails when
|
|
79
|
+
the reported total drops below the `fail_under` threshold. The reported total is the combined figure
|
|
80
|
+
`(covered lines + covered branches) / (valid lines + valid branches)`, so a change that adds only lines without their
|
|
81
|
+
branches lowers it. Branch coverage must additionally stay at or above 95% of all valid branches.
|
|
72
82
|
|
|
73
83
|
Read the gaps with:
|
|
74
84
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
- [Development and Testing](development-testing.md)
|
|
5
5
|
- [PyPI Release](pypi-release.md)
|
|
6
6
|
- [Documentation builds and Read the Docs deployment](documentation-deployment.md)
|
|
7
|
+
- [Defect tracking](defect-tracking.md)
|
|
7
8
|
|
|
8
9
|
```{toctree}
|
|
9
10
|
:hidden:
|
|
@@ -12,4 +13,5 @@ repository-guide
|
|
|
12
13
|
development-testing
|
|
13
14
|
pypi-release
|
|
14
15
|
documentation-deployment
|
|
16
|
+
defect-tracking
|
|
15
17
|
```
|
|
@@ -66,7 +66,7 @@ Roles are freely named by your workflow. Every product is materialized under `an
|
|
|
66
66
|
Subfamily assignment is the point where the pipeline's shape becomes data-dependent: only after the external assign-subfamilies step reads the adopted framework tree is the number of subfamilies known. Do not hand-write one adopt manifest entry per subfamily. Have the external step emit a clean two-column assignment TSV (`unit`, `seqid` — project-specific filtering such as dropping unresolved sequences happens there), adopt that TSV as shown in step 3, then admit the units with `operon fanout`:
|
|
67
67
|
|
|
68
68
|
```bash
|
|
69
|
-
# Inspect the plan first: no files
|
|
69
|
+
# Inspect the plan first: full preflight runs, but no files and no run row.
|
|
70
70
|
operon fanout --assignments-file FIL_000022 \
|
|
71
71
|
--source-file FIL_000012 \
|
|
72
72
|
--entity-type organism --entity-id ORG_000001 \
|
|
@@ -40,7 +40,10 @@ TUI Config screen (`operon tui`, key `6`, QC Profiles tab): a structured form
|
|
|
40
40
|
(description, `applies_to` checkboxes, rule rows) that validates the composed
|
|
41
41
|
document, bumps the `version`, writes the file, and records the same
|
|
42
42
|
content-addressed snapshot `operon evaluate` records — with snapshot history
|
|
43
|
-
and restore-as-new-version built in.
|
|
43
|
+
and restore-as-new-version built in. When a file has been deleted or replaced
|
|
44
|
+
with an older version, the next changed save continues above the highest
|
|
45
|
+
recorded version for that name. See [the TUI reference](../reference/cli-tui.md)
|
|
46
|
+
for the confirmation and recovery behavior.
|
|
44
47
|
|
|
45
48
|
Run the profile:
|
|
46
49
|
|
|
@@ -205,11 +208,11 @@ Grammar:
|
|
|
205
208
|
|
|
206
209
|
- `applies_to` is a mapping with `entity_type` and `file_role` (unlike the list form of `kind: qc` profiles); it selects the target manifest files. Superseded and effectively retired entities are excluded.
|
|
207
210
|
- `sources` names the hit sources the rules can reference. Each source declares:
|
|
208
|
-
- `analysis`: the analysis name whose `analysis_alignments` rows count; only rows of the latest `completed` job per target file contribute.
|
|
211
|
+
- `analysis`: the analysis name whose `analysis_alignments` rows count; only rows of the latest `completed` job per target file contribute. Other completed jobs for the same analysis+file pair are ignored, and a non-zero count is surfaced as `ignored_completed_jobs` in the run output and details.
|
|
209
212
|
- `filter`: which rows count as hits at all (a list of conditions, AND-ed; empty means every row).
|
|
210
213
|
- `best_by`: an ordered best-hit ranking; the first surviving row per seqid is the best hit the rules see. Each entry is a `field` with `direction: asc|desc` (default `asc`), or a `rank` map from value to rank (unmapped values sort after all mapped ones; an entry-level `default` sets their rank explicitly). Without `best_by`, rows order by `hit_rank` ascending.
|
|
211
214
|
- `rules` are evaluated in order and the first match wins. A rule carries a `label` plus exactly one of: a non-empty `when` list of conditions checked against the source's best hit, `absent: true` (the source has no hit row at all for the sequence — tier U above), or `default: true` (catch-all; takes no `source`/`when`/`absent`). A sequence matched by nothing stays unlabeled.
|
|
212
215
|
- Conditions — the grammar is shared between `filter` and `when` — are mappings with a `field` and an `operator`: `>=`, `<=`, `>`, `<`, `==`, `!=` (numeric, with string fallback for equality), `in`/`not_in` (with a `values` list), `between` (with `min`/`max`), `exists`, and `like` (case-insensitive SQL LIKE pattern with `%` and `_` wildcards). A condition may instead be `any: [...]` (a group whose conditions are OR-ed) or `not: {...}` (negation of a single condition); the top-level list is always AND-ed.
|
|
213
|
-
- Fields resolve against the alignment columns (`subject_id`, `hit_rank`, `query_start`, `query_end`, `evalue`, `bitscore`, `percent_identity`, …), then the derived `span` field (`query_end - query_start + 1`) and `seqid` (the query id up to the first whitespace), and finally the keys of the hit row's `extra_json` — parser-specific fields such as `hit_type`, `incomplete`, `short_name`, or `i_evalue`. A missing field
|
|
216
|
+
- Fields resolve against the alignment columns (`subject_id`, `hit_rank`, `query_start`, `query_end`, `evalue`, `bitscore`, `percent_identity`, …), then the derived `span` field (`query_end - query_start + 1`) and `seqid` (the query id up to the first whitespace), and finally the keys of the hit row's `extra_json` — parser-specific fields such as `hit_type`, `incomplete`, `short_name`, or `i_evalue`. A missing field never satisfies a condition in any form: the test is False for every operator (including `!=`, `not_in`, and `exists`), a `not: {...}` negation of a missing-field condition is still False, and a missing-field disjunct inside `any: [...]` counts as unsatisfied. `between` requires numeric operands and raises a validation error naming the field and value otherwise; `in`/`not_in` compare values as strings.
|
|
214
217
|
|
|
215
218
|
Re-running with the same profile content and the same inputs is a no-op; editing the profile re-decides the affected sequences and audits every label change in `changes`.
|