OperonDBS 0.8.4__tar.gz → 0.9.0__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.4 → operondbs-0.9.0}/.github/workflows/publish.yml +6 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/.github/workflows/test.yml +4 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/AGENTS.md +26 -13
- operondbs-0.9.0/LICENSE +22 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/PKG-INFO +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/SOURCES.txt +21 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/PKG-INFO +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/conf_common.py +1 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/overview.md +2 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/metadata-import.md +4 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/remote-execution.md +53 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/remote-first.md +9 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/taxonomy-coverage.md +10 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/behaviors-and-limitations.md +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-analysis.md +1 -1
- operondbs-0.9.0/docs/en/reference/cli-config.md +152 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-decisions-reports.md +3 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-files-qc.md +1 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-project-metadata.md +6 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-tui.md +95 -10
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/index.md +2 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/recipe-fields.md +4 -1
- operondbs-0.9.0/docs/en/reference/resolved-issues.md +95 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/overview.md +2 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/metadata-import.md +3 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/remote-execution.md +90 -5
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/remote-first.md +17 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/taxonomy-coverage.md +10 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/behaviors-and-limitations.md +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-analysis.md +5 -1
- operondbs-0.9.0/docs/zh/reference/cli-config.md +138 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-decisions-reports.md +7 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-files-qc.md +1 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-project-metadata.md +8 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-tui.md +78 -7
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/index.md +2 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/recipe-fields.md +9 -1
- operondbs-0.9.0/docs/zh/reference/resolved-issues.md +87 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/adapters/ncbi_datasets.py +809 -473
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/cli.py +248 -282
- operondbs-0.9.0/operon/config.py +619 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/entity_view.py +212 -142
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/environment.py +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/environment_capture.py +109 -58
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/errors.py +4 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/execution.py +3 -3
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/files.py +5 -5
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/import_wizard.py +3 -4
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/ncbi_reconcile.py +2 -2
- operondbs-0.9.0/operon/pipeline.py +201 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/__init__.py +1 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/_alignment.pyx +3 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/alignment.py +5 -2
- operondbs-0.9.0/operon/qc/imports.py +276 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/remotes.py +9 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/reports.py +1 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/schema.py +166 -6
- operondbs-0.9.0/operon/secrets.py +327 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/sequence_tools.py +190 -111
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/taxonomy.py +49 -15
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tools.py +511 -280
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/actions.py +457 -19
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/app.py +27 -3
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/app.tcss +77 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/data.py +5 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/parity.py +158 -18
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/analyze.py +5 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/common.py +225 -32
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/config.py +374 -18
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/config_classification.py +58 -15
- operondbs-0.9.0/operon/tui/screens/config_coverage.py +143 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/coverage.py +22 -4
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/decisions.py +2 -3
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/derived_ops.py +6 -2
- operondbs-0.9.0/operon/tui/screens/entities.py +687 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/environments.py +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/files.py +85 -4
- operondbs-0.9.0/operon/tui/screens/files_ops.py +627 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/hits.py +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/home.py +24 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/import_wizard.py +3 -3
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/labels.py +1 -1
- operondbs-0.9.0/operon/tui/screens/ncbi_datasets.py +405 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/publish.py +12 -8
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/run_external.py +4 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/runs.py +2 -2
- operondbs-0.9.0/operon/tui/screens/table_import.py +326 -0
- operondbs-0.9.0/operon/tui/screens/taxonomy.py +269 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/splash.py +6 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/utils.py +15 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/workflow.py +3 -3
- {operondbs-0.8.4 → operondbs-0.9.0}/pyproject.toml +2 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_alignment_qc.py +45 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_cli_edges.py +18 -13
- operondbs-0.9.0/tests/unit/test_config_cli.py +290 -0
- operondbs-0.9.0/tests/unit/test_env_audit.py +73 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_environment_capture.py +23 -4
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_execution.py +27 -5
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_lifecycle.py +38 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_ncbi_coverage_gaps.py +68 -0
- operondbs-0.9.0/tests/unit/test_pipeline.py +213 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_remotes.py +3 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_rules_schema_edges.py +67 -0
- operondbs-0.9.0/tests/unit/test_secrets.py +369 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_timetree_snapshots.py +5 -1
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tools_execution_more.py +44 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui.py +351 -18
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_analyze.py +100 -5
- operondbs-0.9.0/tests/unit/test_tui_button_dispatch.py +75 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_cli_parity.py +486 -4
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_config.py +1003 -23
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_derived_ops.py +37 -9
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_flows_more.py +43 -6
- operondbs-0.9.0/tests/unit/test_tui_import_qc.py +306 -0
- operondbs-0.9.0/tests/unit/test_tui_ncbi_datasets.py +607 -0
- operondbs-0.9.0/tests/unit/test_tui_pipeline.py +311 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_publish.py +260 -2
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_screens_more.py +236 -16
- operondbs-0.9.0/tests/unit/test_tui_standardize.py +265 -0
- operondbs-0.9.0/tests/unit/test_tui_table_import.py +782 -0
- operondbs-0.9.0/tests/unit/test_tui_taxonomy.py +967 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_writes.py +694 -17
- operondbs-0.9.0/tests/unit/test_user_config.py +328 -0
- operondbs-0.8.4/LICENSE +0 -661
- operondbs-0.8.4/docs/en/reference/resolved-issues.md +0 -64
- operondbs-0.8.4/docs/zh/reference/resolved-issues.md +0 -56
- operondbs-0.8.4/operon/config.py +0 -238
- operondbs-0.8.4/operon/tui/screens/entities.py +0 -349
- operondbs-0.8.4/operon/tui/screens/files_ops.py +0 -278
- {operondbs-0.8.4 → operondbs-0.9.0}/.gitignore +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/MANIFEST.in +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/dependency_links.txt +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/entry_points.txt +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/requires.txt +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/OperonDBS.egg-info/top_level.txt +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/README.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/README_ZH.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/benchmarks/qc_representative_entities.tsv +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/.readthedocs.yaml +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/extensibility.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/external-analysis.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/files-and-storage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/metadata-and-data-model.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/qc-and-rules.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/release-lifecycle.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/architecture/taxonomy-coverage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/conf.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/defect-tracking.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/development-testing.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/documentation-deployment.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/pypi-release.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/contributor/repository-guide.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/getting-started/daily-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/getting-started/first-project.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/getting-started/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/getting-started/installation.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/getting-started/quickstart.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/backup-migration.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/curation-lifecycle.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/external-analysis.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/file-archiving.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/ncbi-datasets.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/phylogenetics-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/qc-profiles.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/remote-storage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/guides/troubleshooting.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/operations/database-compatibility.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/operations/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/operations/ncbi-recovery-migration.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/operations/qc-performance.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/overview.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-remote.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-taxonomy-lifecycle-admin.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/cli-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/data-model.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/recipe-overview.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/en/reference/recipe-parsers-examples.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/locales/README.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/requirements.txt +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/.readthedocs.yaml +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/extensibility.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/external-analysis.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/files-and-storage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/metadata-and-data-model.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/qc-and-rules.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/release-lifecycle.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/architecture/taxonomy-coverage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/conf.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/defect-tracking.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/development-testing.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/documentation-deployment.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/pypi-release.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/contributor/repository-guide.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/getting-started/daily-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/getting-started/first-project.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/getting-started/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/getting-started/installation.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/getting-started/quickstart.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/backup-migration.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/curation-lifecycle.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/external-analysis.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/file-archiving.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/ncbi-datasets.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/phylogenetics-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/qc-profiles.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/remote-storage.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/guides/troubleshooting.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/operations/database-compatibility.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/operations/index.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/operations/ncbi-recovery-migration.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/operations/qc-performance.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/overview.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-remote.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-taxonomy-lifecycle-admin.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/cli-workflow.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/data-model.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/recipe-overview.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/docs/zh/reference/recipe-parsers-examples.md +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/__main__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/adapters/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/adapters/timetree.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/backup.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/classify.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/coverage.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/database.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/demo.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/export.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/fanout.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/lifecycle.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/lineage.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/metadata_files.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/profiles.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/_parsers.pyx +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/measure.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/qc/parsers.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/release.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/rules.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/shutdown.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/sql.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/table_import.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/timetree.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/assets/splash.png +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/assets/splash.rgb.z +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/screens/classify.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/operon/tui/splash_terminal.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/setup.cfg +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/setup.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/compatibility/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/compatibility/test_python_support.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/helpers.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_analysis_array.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_analysis_resume.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_analysis_shutdown.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_analysis_tools.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_classify_sequences.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_execution_backends.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_fanout_analyze.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_lineage_cascade.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_ncbi_datasets_adapter.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_pipeline_and_release.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_python_packaging.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_qc_remote_measure.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/integration/test_taxonomy_coverage.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/test_correctness.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/test_cython_alignment_parity.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/test_cython_parser_parity.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/test_parser_semantics.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/regression/test_sql_identifier_security.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/__init__.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_classify.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_config_workflow_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_core_coverage_more.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_coverage_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_database_edges_more.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_defect_registry.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_defects_cli.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_docs_projects.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_docs_versions.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_environment.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_execution_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_export.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_fanout.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_files_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_follow.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_import_backup_show.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_import_wizard_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_lineage.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_misc_coverage_more.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_ncbi_edge_cases.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_ncbi_reconcile_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_parser_edge_paths.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_qc_and_rules.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_qc_edges_more.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_qc_measure.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_qc_remote_only.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_recipe_history.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_remote_taxonomy_more.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_remote_transport_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_remotes_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_schema_2_10.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_schema_2_11.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_schema_2_9.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_schema_and_metadata.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_sequence_tools.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_sequences.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_shutdown.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_support_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_table_import_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_taxonomy_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_timetree.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tools_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_m3_loop.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_tui_splash_terminal.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_views_release_reports_edges.py +0 -0
- {operondbs-0.8.4 → operondbs-0.9.0}/tests/unit/test_workflow_cli.py +0 -0
|
@@ -78,6 +78,8 @@ jobs:
|
|
|
78
78
|
runs-on: ubuntu-latest
|
|
79
79
|
steps:
|
|
80
80
|
- uses: actions/checkout@v6
|
|
81
|
+
with:
|
|
82
|
+
persist-credentials: false
|
|
81
83
|
- uses: actions/setup-python@v7
|
|
82
84
|
with:
|
|
83
85
|
python-version: "3.12"
|
|
@@ -133,11 +135,13 @@ jobs:
|
|
|
133
135
|
name: pypi
|
|
134
136
|
url: https://pypi.org/project/operondbs/
|
|
135
137
|
permissions:
|
|
136
|
-
|
|
138
|
+
# This is a standard OIDC Keyless Authorization Statements,
|
|
139
|
+
# NOT a hardcoding token
|
|
140
|
+
id-token: write # nosemgrep: security.hard-coded-tokens
|
|
137
141
|
steps:
|
|
138
142
|
- uses: actions/download-artifact@v8
|
|
139
143
|
with:
|
|
140
144
|
pattern: python-package-*
|
|
141
145
|
path: dist/
|
|
142
146
|
merge-multiple: true
|
|
143
|
-
- uses: pypa/gh-action-pypi-publish@
|
|
147
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
@@ -6,6 +6,9 @@ on:
|
|
|
6
6
|
- master
|
|
7
7
|
pull_request:
|
|
8
8
|
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
9
12
|
# A newer push supersedes an in-flight run of the same ref.
|
|
10
13
|
concurrency:
|
|
11
14
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
@@ -49,6 +52,6 @@ jobs:
|
|
|
49
52
|
python -m pip install --upgrade pip
|
|
50
53
|
python -m pip install -e '.[test]'
|
|
51
54
|
python -m pytest
|
|
52
|
-
- uses: codacy/codacy-coverage-reporter-action@v1.3.0
|
|
55
|
+
- uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0
|
|
53
56
|
with:
|
|
54
57
|
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
|
|
@@ -26,12 +26,10 @@ principle-to-implementation mapping.
|
|
|
26
26
|
|
|
27
27
|
Current version markers (must stay consistent across code and docs):
|
|
28
28
|
|
|
29
|
-
- `operon` 0.
|
|
29
|
+
- `operon` 0.9.0 (`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
|
|
|
33
|
-
The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
34
|
-
|
|
35
33
|
## Repository layout
|
|
36
34
|
|
|
37
35
|
- `operon/` — the Python package (CLI entry points: `operon/cli.py`,
|
|
@@ -56,7 +54,10 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
56
54
|
`tests/regression/test_cython_parser_parity.py`). `measure.py` backs
|
|
57
55
|
`operon qc-measure`, a project-independent measurement-only path whose
|
|
58
56
|
JSON payload can be imported back through `operon import-qc` (the remote
|
|
59
|
-
built-in QC workflow
|
|
57
|
+
built-in QC workflow; `imports.py` is the shared core of that import —
|
|
58
|
+
payload/TSV detection, manifest validation, metric insertion, QC-state
|
|
59
|
+
recomputation and the run record — and `plan_qc_import` its write-free
|
|
60
|
+
preview).
|
|
60
61
|
- `operon/execution.py` — execution backends for external commands:
|
|
61
62
|
`local` subprocess, `slurm` (sbatch submit + squeue poll), and `ssh`
|
|
62
63
|
(Paramiko; HPC head nodes and cloud VMs, optionally through remote
|
|
@@ -68,7 +69,9 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
68
69
|
monitor, a Decisions screen, a Config screen, a Publish screen (nav key
|
|
69
70
|
`7`; release builder + selective export builder with read-only previews),
|
|
70
71
|
a Coverage screen (nav key `8`; taxonomy snapshots, reference sets,
|
|
71
|
-
coverage report generation and `COV_*` report browsing
|
|
72
|
+
coverage report generation and `COV_*` report browsing, plus *Import
|
|
73
|
+
taxonomy…* / *Compile reference set…* write entries mirroring
|
|
74
|
+
`operon taxonomy import`/`operon taxonomy compile`), and the import
|
|
72
75
|
dataset wizard (`operon/tui/screens/import_wizard.py`; Home button or
|
|
73
76
|
global `i`, except on the Files screen where `i` stays ingest). Read
|
|
74
77
|
access lives in
|
|
@@ -83,6 +86,11 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
83
86
|
Confirm → background worker → notify + reload or inline error. Phase 3
|
|
84
87
|
actions in the same module: `import_dataset` (commits wizard drafts
|
|
85
88
|
through the shared single-transaction `import_wizard._commit`),
|
|
89
|
+
`ncbi_datasets` (backing the Home screen's NCBI Datasets import dialog:
|
|
90
|
+
a mandatory dry-run preflight — `dry_run` for offline inputs,
|
|
91
|
+
`plan_only` for accession-only requests — gates Confirm, and Cancel sets
|
|
92
|
+
a cooperative `cancel_event` the core records as an `interrupted`,
|
|
93
|
+
`--resume-run`-able run),
|
|
86
94
|
`reserve_entity_ids`, `create_release`, `export`, `run_coverage`
|
|
87
95
|
(a below-threshold coverage report returns `exit_code=1` in the result
|
|
88
96
|
dict — a warning, not an exception), `preflight_backend`, `run_analysis`
|
|
@@ -110,12 +118,15 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
110
118
|
the project-wide label summary behind the Files screen's `l` binding), which
|
|
111
119
|
has no CLI reader at all. The
|
|
112
120
|
Config screen (`operon/tui/screens/config.py`, nav key `6`) edits
|
|
113
|
-
`config/profiles/*.yaml` (
|
|
114
|
-
each kind has its own form, dispatched by the document's
|
|
115
|
-
classification widgets in `operon/tui/screens/config_classification.py
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
`config/profiles/*.yaml` (kinds `qc`, `sequence_classification` and
|
|
122
|
+
`taxonomy_coverage` — each kind has its own form, dispatched by the document's
|
|
123
|
+
own kind, with the classification widgets in `operon/tui/screens/config_classification.py`,
|
|
124
|
+
the coverage widgets in `operon/tui/screens/config_coverage.py`, and
|
|
125
|
+
`actions.save_classification_profile` / `actions.save_coverage_profile`
|
|
126
|
+
sharing `save_profile`'s version, snapshot and rollback machinery; a
|
|
127
|
+
classification profile whose conditions nest deeper than one `any:`/`not:`
|
|
128
|
+
level, or a coverage profile whose structure exceeds the flat grammar, opens
|
|
129
|
+
read-only) and single recipes inside
|
|
119
130
|
`config/tools.yaml` through structured control-based forms (no free-text
|
|
120
131
|
YAML): every save bumps the `version`, records the same content-addressed
|
|
121
132
|
snapshot the CLI records (`qc_profiles` / `recipe_snapshots`), and
|
|
@@ -132,7 +143,9 @@ The project is licensed AGPL-3.0-or-later (`LICENSE` at the repo root).
|
|
|
132
143
|
`config.py` (project configuration and directory layout), `files.py`
|
|
133
144
|
(immutable manifest archival and verification), `profiles.py` +
|
|
134
145
|
`rules.py` (versioned QC profiles and the decision engine),
|
|
135
|
-
`workflow.py` (state machine and run logs), `
|
|
146
|
+
`workflow.py` (state machine and run logs), `pipeline.py` (the
|
|
147
|
+
four-stage ingest → standardize → QC → evaluate runner shared by
|
|
148
|
+
`run-pipeline`'s CLI and TUI), `tools.py` (external-tool
|
|
136
149
|
recipes from `config/tools.yaml`), `taxonomy.py` + `coverage.py` (frozen
|
|
137
150
|
NCBI Taxonomy snapshots and coverage denominators), `release.py` +
|
|
138
151
|
`export.py` (immutable releases and selective exports), `lifecycle.py`
|
|
@@ -315,7 +328,7 @@ change:
|
|
|
315
328
|
`docs/<language>/.readthedocs.yaml`, and the registry in
|
|
316
329
|
`tests/unit/test_docs_projects.py`
|
|
317
330
|
|
|
318
|
-
Version markers in docs (`operon` 0.
|
|
331
|
+
Version markers in docs (`operon` 0.9.0, database schema 2.11, metadata
|
|
319
332
|
schema 1.4) must match `pyproject.toml` and the code. Do not write the
|
|
320
333
|
current values literally in Markdown sources: use the `myst_substitutions`
|
|
321
334
|
references `{{ operon_version }}`, `{{ db_schema }}`, and
|
operondbs-0.9.0/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2026 HYLi360.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
4
|
+
are permitted provided that the following conditions are met:
|
|
5
|
+
|
|
6
|
+
Redistributions of source code must retain the above copyright notice, this list
|
|
7
|
+
of conditions and the following disclaimer.
|
|
8
|
+
|
|
9
|
+
Redistributions in binary form must reproduce the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer in the documentation and/or
|
|
11
|
+
other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
20
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OperonDBS
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
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
|
-
License-Expression:
|
|
6
|
+
License-Expression: BSD-2-Clause
|
|
7
7
|
Project-URL: Repository, https://github.com/HYLi360/Operon
|
|
8
8
|
Project-URL: Issues, https://github.com/HYLi360/Operon/issues
|
|
9
9
|
Classifier: Operating System :: MacOS
|
|
@@ -61,6 +61,7 @@ docs/en/operations/ncbi-recovery-migration.md
|
|
|
61
61
|
docs/en/operations/qc-performance.md
|
|
62
62
|
docs/en/reference/behaviors-and-limitations.md
|
|
63
63
|
docs/en/reference/cli-analysis.md
|
|
64
|
+
docs/en/reference/cli-config.md
|
|
64
65
|
docs/en/reference/cli-decisions-reports.md
|
|
65
66
|
docs/en/reference/cli-files-qc.md
|
|
66
67
|
docs/en/reference/cli-project-metadata.md
|
|
@@ -119,6 +120,7 @@ docs/zh/operations/ncbi-recovery-migration.md
|
|
|
119
120
|
docs/zh/operations/qc-performance.md
|
|
120
121
|
docs/zh/reference/behaviors-and-limitations.md
|
|
121
122
|
docs/zh/reference/cli-analysis.md
|
|
123
|
+
docs/zh/reference/cli-config.md
|
|
122
124
|
docs/zh/reference/cli-decisions-reports.md
|
|
123
125
|
docs/zh/reference/cli-files-qc.md
|
|
124
126
|
docs/zh/reference/cli-project-metadata.md
|
|
@@ -154,12 +156,14 @@ operon/lifecycle.py
|
|
|
154
156
|
operon/lineage.py
|
|
155
157
|
operon/metadata_files.py
|
|
156
158
|
operon/ncbi_reconcile.py
|
|
159
|
+
operon/pipeline.py
|
|
157
160
|
operon/profiles.py
|
|
158
161
|
operon/release.py
|
|
159
162
|
operon/remotes.py
|
|
160
163
|
operon/reports.py
|
|
161
164
|
operon/rules.py
|
|
162
165
|
operon/schema.py
|
|
166
|
+
operon/secrets.py
|
|
163
167
|
operon/sequence_tools.py
|
|
164
168
|
operon/shutdown.py
|
|
165
169
|
operon/sql.py
|
|
@@ -176,6 +180,7 @@ operon/qc/__init__.py
|
|
|
176
180
|
operon/qc/_alignment.pyx
|
|
177
181
|
operon/qc/_parsers.pyx
|
|
178
182
|
operon/qc/alignment.py
|
|
183
|
+
operon/qc/imports.py
|
|
179
184
|
operon/qc/measure.py
|
|
180
185
|
operon/qc/parsers.py
|
|
181
186
|
operon/tui/__init__.py
|
|
@@ -194,6 +199,7 @@ operon/tui/screens/classify.py
|
|
|
194
199
|
operon/tui/screens/common.py
|
|
195
200
|
operon/tui/screens/config.py
|
|
196
201
|
operon/tui/screens/config_classification.py
|
|
202
|
+
operon/tui/screens/config_coverage.py
|
|
197
203
|
operon/tui/screens/coverage.py
|
|
198
204
|
operon/tui/screens/decisions.py
|
|
199
205
|
operon/tui/screens/derived_ops.py
|
|
@@ -205,9 +211,12 @@ operon/tui/screens/hits.py
|
|
|
205
211
|
operon/tui/screens/home.py
|
|
206
212
|
operon/tui/screens/import_wizard.py
|
|
207
213
|
operon/tui/screens/labels.py
|
|
214
|
+
operon/tui/screens/ncbi_datasets.py
|
|
208
215
|
operon/tui/screens/publish.py
|
|
209
216
|
operon/tui/screens/run_external.py
|
|
210
217
|
operon/tui/screens/runs.py
|
|
218
|
+
operon/tui/screens/table_import.py
|
|
219
|
+
operon/tui/screens/taxonomy.py
|
|
211
220
|
tests/__init__.py
|
|
212
221
|
tests/helpers.py
|
|
213
222
|
tests/compatibility/__init__.py
|
|
@@ -236,6 +245,7 @@ tests/unit/__init__.py
|
|
|
236
245
|
tests/unit/test_alignment_qc.py
|
|
237
246
|
tests/unit/test_classify.py
|
|
238
247
|
tests/unit/test_cli_edges.py
|
|
248
|
+
tests/unit/test_config_cli.py
|
|
239
249
|
tests/unit/test_config_workflow_edges.py
|
|
240
250
|
tests/unit/test_core_coverage_more.py
|
|
241
251
|
tests/unit/test_coverage_edges.py
|
|
@@ -244,6 +254,7 @@ tests/unit/test_defect_registry.py
|
|
|
244
254
|
tests/unit/test_defects_cli.py
|
|
245
255
|
tests/unit/test_docs_projects.py
|
|
246
256
|
tests/unit/test_docs_versions.py
|
|
257
|
+
tests/unit/test_env_audit.py
|
|
247
258
|
tests/unit/test_environment.py
|
|
248
259
|
tests/unit/test_environment_capture.py
|
|
249
260
|
tests/unit/test_execution.py
|
|
@@ -261,6 +272,7 @@ tests/unit/test_ncbi_coverage_gaps.py
|
|
|
261
272
|
tests/unit/test_ncbi_edge_cases.py
|
|
262
273
|
tests/unit/test_ncbi_reconcile_edges.py
|
|
263
274
|
tests/unit/test_parser_edge_paths.py
|
|
275
|
+
tests/unit/test_pipeline.py
|
|
264
276
|
tests/unit/test_qc_and_rules.py
|
|
265
277
|
tests/unit/test_qc_edges_more.py
|
|
266
278
|
tests/unit/test_qc_measure.py
|
|
@@ -275,6 +287,7 @@ tests/unit/test_schema_2_10.py
|
|
|
275
287
|
tests/unit/test_schema_2_11.py
|
|
276
288
|
tests/unit/test_schema_2_9.py
|
|
277
289
|
tests/unit/test_schema_and_metadata.py
|
|
290
|
+
tests/unit/test_secrets.py
|
|
278
291
|
tests/unit/test_sequence_tools.py
|
|
279
292
|
tests/unit/test_sequences.py
|
|
280
293
|
tests/unit/test_shutdown.py
|
|
@@ -287,14 +300,22 @@ tests/unit/test_tools_edges.py
|
|
|
287
300
|
tests/unit/test_tools_execution_more.py
|
|
288
301
|
tests/unit/test_tui.py
|
|
289
302
|
tests/unit/test_tui_analyze.py
|
|
303
|
+
tests/unit/test_tui_button_dispatch.py
|
|
290
304
|
tests/unit/test_tui_cli_parity.py
|
|
291
305
|
tests/unit/test_tui_config.py
|
|
292
306
|
tests/unit/test_tui_derived_ops.py
|
|
293
307
|
tests/unit/test_tui_flows_more.py
|
|
308
|
+
tests/unit/test_tui_import_qc.py
|
|
294
309
|
tests/unit/test_tui_m3_loop.py
|
|
310
|
+
tests/unit/test_tui_ncbi_datasets.py
|
|
311
|
+
tests/unit/test_tui_pipeline.py
|
|
295
312
|
tests/unit/test_tui_publish.py
|
|
296
313
|
tests/unit/test_tui_screens_more.py
|
|
297
314
|
tests/unit/test_tui_splash_terminal.py
|
|
315
|
+
tests/unit/test_tui_standardize.py
|
|
316
|
+
tests/unit/test_tui_table_import.py
|
|
317
|
+
tests/unit/test_tui_taxonomy.py
|
|
298
318
|
tests/unit/test_tui_writes.py
|
|
319
|
+
tests/unit/test_user_config.py
|
|
299
320
|
tests/unit/test_views_release_reports_edges.py
|
|
300
321
|
tests/unit/test_workflow_cli.py
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: OperonDBS
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
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
|
-
License-Expression:
|
|
6
|
+
License-Expression: BSD-2-Clause
|
|
7
7
|
Project-URL: Repository, https://github.com/HYLi360/Operon
|
|
8
8
|
Project-URL: Issues, https://github.com/HYLi360/Operon/issues
|
|
9
9
|
Classifier: Operating System :: MacOS
|
|
@@ -95,7 +95,7 @@ def source_constant(module: str, name: str) -> str:
|
|
|
95
95
|
try:
|
|
96
96
|
imported = __import__(f"operon.{module}", fromlist=[name])
|
|
97
97
|
return str(getattr(imported, name))
|
|
98
|
-
except
|
|
98
|
+
except (ImportError, AttributeError):
|
|
99
99
|
source = (REPO_ROOT / "operon" / f"{module}.py").read_text(encoding="utf-8")
|
|
100
100
|
match = re.search(rf'^{name} = "([^"]+)"', source, re.MULTILINE)
|
|
101
101
|
if match is None:
|
|
@@ -120,6 +120,8 @@ How the principles map to implementations:
|
|
|
120
120
|
| `operon/profiles.py` | Loads and validates the versioned YAML profiles shared by the rule engine and taxonomy coverage |
|
|
121
121
|
| `operon/metadata_files.py` | Compatibility notice for the retired live metadata TSV directory; SQLite is the only writable metadata source |
|
|
122
122
|
| `operon/qc/measure.py` | Project-independent `operon qc-measure` measurement path whose JSON payload is imported back through `operon import-qc` |
|
|
123
|
+
| `operon/qc/imports.py` | The shared `operon import-qc` core: JSON-payload/TSV detection, validation against the manifest, metric insertion, QC-state recomputation and the run record; `plan_qc_import` is the write-free preview the TUI shows |
|
|
124
|
+
| `operon/pipeline.py` | The shared `operon run-pipeline` core: the ingest → standardize → QC → evaluate stages, `plan_pipeline`'s write-free preflight (resolved profile, entity checks, the curated-decision gate) and a `progress` callback the CLI prints |
|
|
123
125
|
| `operon/classify.py` | `sequence_classification` profiles: labels per sequence from stored alignment hits into `sequence_labels` |
|
|
124
126
|
| `operon/sequence_tools.py` | `extract-domains` / `select-sequences`: materializes FASTA subsets from stored alignment intervals |
|
|
125
127
|
| `operon/fanout.py` | Data-derived fan-out of registered sequence files into per-unit FASTAs under `analysis/derived/` with `file_lineage` edges |
|
|
@@ -19,6 +19,10 @@ operon import table --table organisms --file organisms.csv \
|
|
|
19
19
|
--on-conflict update --yes
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
The same template/preview flow is available in the TUI: the Home screen's
|
|
23
|
+
*Import table* dialog generates templates and runs the mandatory preview
|
|
24
|
+
before Confirm (see the reference's Import table section).
|
|
25
|
+
|
|
22
26
|
Import behavior:
|
|
23
27
|
|
|
24
28
|
- Only manually managed entity/accession tables are accepted. System-managed tables such as `files`, QC results, and decisions cannot be overwritten by table import.
|
|
@@ -94,4 +94,56 @@ recipes:
|
|
|
94
94
|
|
|
95
95
|
See [Recipe Field Reference](../reference/recipe-fields.md#slurm-resource-overrides) for the complete field list, including the `array` / `array_concurrency` job-array keys, which apply equally to local Slurm and to remote Slurm over SSH.
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
## Smoke-testing a deployment
|
|
98
|
+
|
|
99
|
+
The automated tests for Slurm and SSH use simulated sbatch/squeue and in-memory SSH/SFTP implementations. The SSH/SFTP, remote-only analysis, and remote Slurm paths have also been smoke-tested against real clusters:
|
|
100
|
+
|
|
101
|
+
- 2026-09-04 — Linux OpenSSH login node, shared GPFS filesystem, Slurm compute node;
|
|
102
|
+
- 2026-09-20 — OpenSSH login node with `sbatch`/`squeue`/`sacct` and a `cu` partition, mirror and compute root on one shared filesystem: `evict` → remote-only `analyze` of an HMMER recipe → `pull`, over 13 MB of input.
|
|
103
|
+
|
|
104
|
+
Each deployment should still run a short task of its own; the checklist, reference run and pitfalls below are what validated the 2026-09-20 deployment.
|
|
105
|
+
|
|
106
|
+
### Checklist
|
|
107
|
+
|
|
108
|
+
1. **Mirror reachability and host key.** `operon remotes` must list the mirror as `ok`; an unknown host is rejected until its key is in `known_hosts` or `host_key_sha256` is pinned.
|
|
109
|
+
2. **One filesystem, two node classes.** `remote_root` (inherited from `storage_remote` by default) must be visible from the login node that runs `sbatch` and from the compute nodes.
|
|
110
|
+
3. **Scheduler.** `sbatch`, `squeue` and `sacct` must be in the login node's non-interactive `PATH`, and the configured partition must exist.
|
|
111
|
+
4. **Tools on the compute side.** Every recipe `executable` must be on the `PATH` the submitted job inherits. `operon tools-check` probes the local machine only, so it cannot validate the remote side; a binary reachable only from an interactive shell, or only from a conda environment the non-interactive shell does not activate, fails at probe or submit time.
|
|
112
|
+
5. **Reference database.** Deploy it in advance at the remote target path and declare `database_checksum`; prefer a project-relative `database` so the path is mapped into the remote root (see [Databases on SSH remotes](../reference/recipe-fields.md#databases-on-ssh-remotes)).
|
|
113
|
+
6. **A short recipe over one small file**, so the smoke run takes minutes rather than hours.
|
|
114
|
+
|
|
115
|
+
To also exercise remote-only input consumption, configure `execution.ssh.storage_remote` as in [Remote-First Operation](remote-first.md) and evict the file before the run.
|
|
116
|
+
|
|
117
|
+
### Reference smoke run
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
operon evict --remote mycluster --file-id FIL_000001 # input becomes REMOTE_ONLY
|
|
121
|
+
operon analyze --analysis <recipe> --entity-id <entity> --threads 24 --backend ssh
|
|
122
|
+
operon analyze --analysis <recipe> --entity-id <entity> --threads 24 --backend ssh # must report cached
|
|
123
|
+
operon pull --remote mycluster --file-id FIL_000001 # restore the local bytes
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Then check both planes:
|
|
127
|
+
|
|
128
|
+
| Where | What to verify |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `analysis_jobs` | `launcher = [ssh:user@host]`, `status = completed`, `output_sha256`, `environment_id`, `recipe_snapshot_id`, and a `command` naming the resolved database |
|
|
131
|
+
| `execution_details` | `scheduler_job_id`, `slurm_elapsed_seconds`, `host`, and the remote `script` path under `remote_root/logs/` |
|
|
132
|
+
| `execution_environments` | the probe describes the **compute node** (CPU model, cpuset), not the login node |
|
|
133
|
+
| remote host | `logs/<run_id>.sbatch` contains rewritten paths only — the `cd` and every project path inside `remote_root`; `<run_id>.exitcode` holds `0` |
|
|
134
|
+
| both sides | the retrieved output's SHA-256 equals `sha256sum` of the remote file |
|
|
135
|
+
| local `logs/` | `<run_id>.stdout.log` / `.stderr.log` are copies retrieved from the remote job |
|
|
136
|
+
| `changes` / `locations` | the eviction to `REMOTE_ONLY` and the restore to `CHECKSUM_VERIFIED` are audited, and the placeholder under `.operon/placeholders/` is gone after `pull` |
|
|
137
|
+
|
|
138
|
+
A second identical run must report `cached` for the file instead of submitting another job; if it resubmits, the cache identity changed (a different backend or host/root, an edited recipe, or a different resolved `database`).
|
|
139
|
+
|
|
140
|
+
### Pitfalls
|
|
141
|
+
|
|
142
|
+
- **A `database` outside the project root is never mapped.** Absolute values — including `~/...`, which is expanded before mapping — are passed through verbatim, so the compute side must have that exact path. A recipe that works locally with `/data/db/Pfam-A.hmm` or `~/resources/hmm/PF00010.hmm` fails remotely. A project-relative value is mapped into `remote_root` instead, which is what most recipes want.
|
|
143
|
+
- **`--dry-run` validates what needs no command execution.** The local database existence check runs, and for a remote `reference` database so does the provisioning stat, so a database that exists nowhere fails the preview with the message a real run reports — `reference database not found: <path>; edit config/tools.yaml`, or `remote reference database is not provisioned at <path>` — and the command exits non-zero. A remote `mutable_cache` has nothing to verify yet, and the tool version is still reported as `not probed (backend=…)` because probing it would execute a command. Validate a deployment with one real file, not with `--dry-run`.
|
|
144
|
+
- **A remote `reference` database must declare `database_checksum`.** Without it the run is rejected before anything is submitted: `remote reference databases require database_checksum so cache identity does not depend on a missing local path`.
|
|
145
|
+
- **The reference database is not a manifest file.** `push`, `evict` and `pull` move ingested files only, so `operon remotes` does not count the database and a new mirror root needs it redeployed by hand.
|
|
146
|
+
- **Remote-only semantics come from the backend, not from the file's status.** Any `ssh` run with a non-empty `remote_root` skips the local database existence check, requires `database_checksum`, and mixes the SSH location into the database cache identity. Results are therefore not shared between the `local` and `ssh` backends, or between two hosts/roots — a backend switch recomputes by design.
|
|
147
|
+
- **The input never travels back on its own.** A locally present input is uploaded over SFTP; a `REMOTE_ONLY` input is checked against the local manifest, the remote manifest and the live remote bytes, then consumed in place. Either way the bytes stay where they are, and `pull` remains an explicit step.
|
|
148
|
+
- **Tool outputs may embed the command that produced them.** HMMER's `--tblout`/`--domtblout` banner records the query and target paths, the full argv, the working directory and the date, so the same input analyzed locally and remotely yields different bytes even when the hit table is identical (observed on one file: 135 identical data lines, 5 differing banner lines, `output_sha256` `a64cc0c5…` → `1a0fc453…`). Treat `output_sha256` as host- and path-specific: a re-run on another backend overwrites the recorded output, and the older job row's hash then no longer matches the file on disk — such a row is marked `superseded` the next time it is hit. This is another reason the cache identity includes the SSH location.
|
|
149
|
+
- **Tool versions are probed through the backend, so keep the two installations compatible.** `qc-measure` payloads are the one place where a version mismatch is only a warning; for `analyze` results, a remote tool of a different version changes the recorded `tool_version` and therefore the cache identity.
|
|
@@ -124,6 +124,15 @@ operon pull --remote mycluster --file-id FIL_000001
|
|
|
124
124
|
|
|
125
125
|
`REMOTE_ONLY` files make the local database and the remote mirror root two separate backup targets; see [Backup, Migration, and Resumption](backup-migration.md).
|
|
126
126
|
|
|
127
|
+
## Common pitfalls
|
|
128
|
+
|
|
129
|
+
- **The reference database is not mirrored.** `push`, `evict` and `pull` move manifest files only, so a recipe `database` must be deployed at the remote target path by hand — with a `database_checksum` for a `reference` database — and redeployed whenever the mirror moves to another host or root.
|
|
130
|
+
- **Keep `database` project-relative.** An absolute or `~/...` value reaches the remote command verbatim and must exist at that exact path there; a project-relative value is mapped into the remote root instead.
|
|
131
|
+
- **`--dry-run` only previews.** It skips the database checks and does not probe the tool through the backend, so a deployment is validated by the first real run, not by a dry run.
|
|
132
|
+
- **`analyze` hydrates nothing.** A `REMOTE_ONLY` input is consumed in place and stays `REMOTE_ONLY`; `standardize`, `release` and `export` still need local bytes, so `pull` first.
|
|
133
|
+
- **Results are location-scoped.** The database identity includes the SSH host and root, so the same recipe does not share cached results between the `local` and `ssh` backends, or between two hosts.
|
|
134
|
+
- **A backend switch is not just a speed setting.** Any `ssh` run with a non-empty `remote_root` requires `database_checksum` and skips the local database existence check. See [Remote Execution with Slurm and SSH](remote-execution.md#pitfalls) for the field-level rules and the rest of the list.
|
|
135
|
+
|
|
127
136
|
## Limitations
|
|
128
137
|
|
|
129
138
|
- `run-external` and `analyze` are synchronous and blocking: the local CLI process holds the remote job for its whole lifetime. Interrupting the process or hitting `--timeout` cancels the remote job (`scancel` for remote Slurm, TERM/KILL to the process group for direct SSH). There is no submit-and-disconnect mode that recovers a job later.
|
|
@@ -28,7 +28,7 @@ Import, compilation, and reporting are explicit commands. Imported source files
|
|
|
28
28
|
|
|
29
29
|
## Prepare a coverage profile
|
|
30
30
|
|
|
31
|
-
`operon init` creates `config/profiles/coverage_viridiplantae_v1.yaml` as an example. It is a template, not a universal standard. Before production use, review the clade, exclusion rules, and thresholds, and save the result under a filename that reflects the study scope. QC and coverage profiles share the directory but are distinguished by the required `kind` field.
|
|
31
|
+
`operon init` creates `config/profiles/coverage_viridiplantae_v1.yaml` as an example. It is a template, not a universal standard. Before production use, review the clade, exclusion rules, and thresholds, and save the result under a filename that reflects the study scope. QC and coverage profiles share the directory but are distinguished by the required `kind` field. The TUI's Config screen (`operon tui`, key `6`, QC Profiles tab) edits coverage profiles with the same version bump and content-addressed snapshot recording as the CLI; a profile whose structure exceeds the form opens read-only there. Hand-editing the YAML file remains fully supported.
|
|
32
32
|
|
|
33
33
|
```yaml
|
|
34
34
|
kind: taxonomy_coverage
|
|
@@ -94,6 +94,10 @@ After import:
|
|
|
94
94
|
|
|
95
95
|
Repeating an import with the same version and bytes reuses the snapshot. The same version label with different bytes is a conflict and is rejected.
|
|
96
96
|
|
|
97
|
+
The TUI offers the same import on the Coverage screen (*Import taxonomy…*
|
|
98
|
+
button) with the equivalent command preview; a running import cannot be
|
|
99
|
+
interrupted from the TUI.
|
|
100
|
+
|
|
97
101
|
## Compile the immutable denominator
|
|
98
102
|
|
|
99
103
|
```bash
|
|
@@ -112,6 +116,11 @@ taxonomy/reference_sets/
|
|
|
112
116
|
└── coverage_viridiplantae_v1@2026-08-01.provenance.json
|
|
113
117
|
```
|
|
114
118
|
|
|
119
|
+
The TUI offers the same compilation on the Coverage screen (*Compile
|
|
120
|
+
reference set…* button): the profile and the taxonomy version are picked
|
|
121
|
+
from dropdowns that list only READY snapshots; a running compile cannot be
|
|
122
|
+
interrupted from the TUI.
|
|
123
|
+
|
|
115
124
|
Each TSV row is a target taxon with fixed columns:
|
|
116
125
|
|
|
117
126
|
```text
|
|
@@ -131,7 +131,7 @@ remaining bullets are intended-but-implicit semantics or accepted limitations.
|
|
|
131
131
|
- **A control ignores a click while its press animation runs.** Textual's `Button` swallows a click while the button still carries its `-active` press effect (roughly 0.2 s), so a rapid double-click on the same button is lost; the TUI's dialogs are built around one Confirm per action, and tests wait for the effect to clear before clicking again.
|
|
132
132
|
- **The Files screen's derived-artifact dialogs leave registration to adopt.** *Extract domains* and *Select sequences* write their FASTA through the core and then hand the path to the adopt dialog (`derived_from` = the source file), because neither command registers its output — the same two-step flow as the CLI. The adopt dialog's manifest mode requires a *Preview* before Confirm (the parsed item count is shown), and `fanout`'s dry run is a mandatory first step that performs the real preflight and writes nothing at all (no run row either); changing an input invalidates the preview and disables Confirm again.
|
|
133
133
|
- **The classification-profile form stops at one level of `any:`/`not:`.** The Config screen's `sequence_classification` editor models flat conditions, one `any:` group and one `not:` negation — the same forms the qc editor offers for its rules. A profile that nests deeper (or whose `sources`/`rules` are not mappings) opens read-only: the reason is printed, *Save profile* is disabled, and the file is never rewritten, so hand-written structure survives every visit to the editor. Unknown keys are preserved verbatim at every level, and the composed document keeps the original key order.
|
|
134
|
-
- **A profile's kind belongs to the file, not the editor.** The TUI routes a document to the qc or
|
|
134
|
+
- **A profile's kind belongs to the file, not the editor.** The TUI routes a document to the qc, classification or coverage form by the `kind` it finds on disk, and a save refuses to cross kinds (editing a `kind: qc` file with a classification document, or vice versa, raises instead of writing). The `taxonomy_coverage` editor models the flat coverage grammar (NCBI source, root TaxIDs, family/genus ranks, exclusion filters, per-rank thresholds); a profile whose structure exceeds the form opens read-only, and unknown keys are preserved verbatim at the document and section level.
|
|
135
135
|
|
|
136
136
|
### TimeTree
|
|
137
137
|
|
|
@@ -250,7 +250,7 @@ remaining bullets are intended-but-implicit semantics or accepted limitations.
|
|
|
250
250
|
- **Only some symlinks are rebased.** Absolute symlinks under `standardized/` that point inside the project are rewritten to relative targets when the backup is created; relative links, links elsewhere in the tree and absolute targets outside the project keep their exact text, and there is no restore command (`backup.py`).
|
|
251
251
|
- **`backup verify` rejects unexpected extra files**, not only missing or changed ones (`backup.py`).
|
|
252
252
|
- **The wizard holds the write lock while hashing and copying.** Ingest happens inside one large transaction; on failure the database rolls back, buffered JSONL records are discarded, and only newly created `raw/` targets are deleted — pre-existing targets stay (`import_wizard.py`).
|
|
253
|
-
- **The wizard re-hashes inputs, burns IDs and needs a user name.** Each input is hashed two to three times and the first pass runs outside the write lock; `db.next_id()` reserves and commits IDs while prompts are still open, so a cancelled wizard permanently burns IDs; the actor is
|
|
253
|
+
- **The wizard re-hashes inputs, burns IDs and needs a user name.** Each input is hashed two to three times and the first pass runs outside the write lock; `db.next_id()` reserves and commits IDs while prompts are still open, so a cancelled wizard permanently burns IDs; the actor is the resolved audit actor (see [user configuration](cli-config.md)), so container or cron runs without `USER`, a local account entry, or `identity.actor` record a NULL actor; and new entities are forced to `METADATA_VALIDATED` (`import_wizard.py`, `database.py`).
|
|
254
254
|
- **The wizard needs a TTY and accepts only regular files** (no directory artifacts). If another process consumes a shown ID in the meantime, preflight raises and the wizard must be restarted (`import_wizard.py`).
|
|
255
255
|
- **Known issue: the wizard breaks when its draft outlives the database state.** Repopulating a page assigns the draft's remembered IDs to the pickers; if an entity was retired or removed while the wizard was open, the `Select` value is no longer among the freshly loaded options and `InvalidSelectValueError` is raised on the UI thread inside the worker callback, so the page never renders and no inline error appears. For the same reason a failed startup leaves navigation enabled with an empty reserved-ID map, and pressing Next with a typed organism name then raises an uncaught `KeyError`. Leaving the sequencing/annotation page clears only the enable checkbox, so stale widget text can reappear when the section is re-enabled (`import_wizard.py`, TUI).
|
|
256
256
|
- **The demo project is byte-deterministic and deliberately broken.** The synthetic project uses a fixed seed (20260816), fixed contig lengths and 400×100 bp reads with hard-coded IDs (with a gap at `ANN_000002`), release `2026.08.demo` and project `PRJ_DEMO_001`; it ships a broken annotation (601-nt CDS, dangling mRNA parent), constant `'I'` read quality and an R2 that is unrelated random DNA rather than the reverse complement; its sources live in `examples/synthetic_source`, which `full` backups copy (`demo.py`, `backup.py`).
|
|
@@ -57,7 +57,7 @@ Outside `--dry-run`, `analyze` prints one progress line per file as processing a
|
|
|
57
57
|
|
|
58
58
|
Slurm array submission: when the recipe's `slurm:` block sets `array: true`, the selected executor supports job arrays (the local Slurm backend, or the SSH backend with `scheduler: slurm`), and at least two files in the batch miss the cache, those files are submitted as a single Slurm job array instead of one job per file; `array_concurrency: N` throttles how many array tasks run concurrently (Slurm `%N`). In every other case the per-file submission path is used unchanged. Each file still gets its own `workflow_runs` row, with the per-task scheduler job ID recorded as `<array_id>_<task_index>`. Cache behavior is unchanged: array participation never enters the parameter fingerprint or cache identity, so cache hits and output adoption work identically with array submission on or off. See "Slurm array submission" in the [Recipe field reference](recipe-fields.md).
|
|
59
59
|
|
|
60
|
-
`--dry-run` lists the plan without execution. Status values are `cached` (completed cache hit), `adoptable` (verified old output will be adopted), or `planned` (execution will run). The output column contains planned output paths, and `tool_version` contains the detected version.
|
|
60
|
+
`--dry-run` lists the plan without execution. Status values are `cached` (completed cache hit), `adoptable` (verified old output will be adopted), or `planned` (execution will run). The output column contains planned output paths, and `tool_version` contains the detected version on the local backend; a non-local backend reports `not probed (backend=…)` because the probe itself would open a connection. A dry run does perform the validations that need no command execution — the recipe database's local existence, a remote reference database's provisioning (a stat over the backend), and the `database_checksum` rule — so a plan that cannot execute reports the same error a real run would, and the command exits non-zero.
|
|
61
61
|
|
|
62
62
|
`--param` can set only parameters declared by the recipe. Missing required parameters, unknown parameters, repeated values, or values failing `pattern`/`choices` are configuration errors. Default `busco_lineage` usage:
|
|
63
63
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# User configuration
|
|
2
|
+
|
|
3
|
+
`operon` keeps user-level settings in one optional YAML file outside the
|
|
4
|
+
project. It never replaces project configuration: `project.yaml` still owns the
|
|
5
|
+
storage layout, database path, resources, and execution backends, while the user
|
|
6
|
+
file owns the handful of settings that belong to *you* rather than to a project.
|
|
7
|
+
|
|
8
|
+
```{note}
|
|
9
|
+
The file is optional. Without it, built-in defaults apply and the per-user
|
|
10
|
+
identity falls back to the environment, exactly as before.
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Location
|
|
14
|
+
|
|
15
|
+
The user configuration follows the XDG Base Directory specification:
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
$XDG_CONFIG_HOME/operon/config.yml # typically ~/.config/operon/config.yml
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
- `XDG_CONFIG_HOME` unset or empty → `~/.config/operon/config.yml`.
|
|
22
|
+
- There is no `OPERON_CONFIG_HOME`: the path is fully determined by XDG.
|
|
23
|
+
- `operon` never creates `~/.operon`, and there is no per-project user file.
|
|
24
|
+
- The file is written with mode `0600`, its directory with `0700`.
|
|
25
|
+
- `operon config` is project independent: it never opens `operon.sqlite` and
|
|
26
|
+
works before `operon init` and outside any project directory.
|
|
27
|
+
|
|
28
|
+
## Precedence
|
|
29
|
+
|
|
30
|
+
Command-line flags win over environment variables, environment variables win
|
|
31
|
+
over the file, and the file wins over built-in defaults.
|
|
32
|
+
|
|
33
|
+
| Setting | Flag | Environment | User file | Fallback |
|
|
34
|
+
| --- | --- | --- | --- | --- |
|
|
35
|
+
| Audit actor | `--actor` | `OPERON_ACTOR`, `USER`, `LOGNAME`, `USERNAME` | `identity.actor` | the local account (`getpass`), then no actor |
|
|
36
|
+
| NCBI contact | `--email` | `NCBI_EMAIL` | `ncbi.email` | unset |
|
|
37
|
+
| NCBI API key | `--api-key` | `NCBI_API_KEY` | never stored in the file | a stored secret (see below) |
|
|
38
|
+
| Terminal graphics | — | `OPERON_SPLASH` | `ui.splash` | `auto` (detection) |
|
|
39
|
+
|
|
40
|
+
Two details are worth stating explicitly:
|
|
41
|
+
|
|
42
|
+
- The local account sits between the environment and the file: on a normal
|
|
43
|
+
login the actor is still `$USER`, and `identity.actor` only fills the gap in
|
|
44
|
+
containers and cron jobs where no login variable and no password entry exist.
|
|
45
|
+
- Operations that require an actor (`retire --apply`, `restore --apply`, the
|
|
46
|
+
TUI lifecycle and curate dialogs) fail with a clear error instead of writing
|
|
47
|
+
a nameless audit row.
|
|
48
|
+
|
|
49
|
+
## Keys
|
|
50
|
+
|
|
51
|
+
| Key | Type | Default | Meaning |
|
|
52
|
+
| --- | --- | --- | --- |
|
|
53
|
+
| `schema_version` | integer | `1` | Document version; written by `operon config init` |
|
|
54
|
+
| `identity.actor` | string | `""` | Fallback audit actor |
|
|
55
|
+
| `ncbi.email` | string | `""` | NCBI contact address for API requests |
|
|
56
|
+
| `ui.splash` | choice | `auto` | `auto`, `text`, `blocks`, or `kitty` |
|
|
57
|
+
|
|
58
|
+
Unknown keys are preserved in the file but ignored by this version, and
|
|
59
|
+
`operon config check` reports them. Keys that look like secret material
|
|
60
|
+
(`…api_key`, `token`, `secret`, `password`, `credential`) are refused by
|
|
61
|
+
`operon config set`: credentials belong in a secret backend.
|
|
62
|
+
|
|
63
|
+
## Commands
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
operon config path
|
|
67
|
+
operon config show [--effective] [--json]
|
|
68
|
+
operon config get KEY
|
|
69
|
+
operon config set KEY VALUE
|
|
70
|
+
operon config unset KEY
|
|
71
|
+
operon config check
|
|
72
|
+
operon config init [--force]
|
|
73
|
+
operon config secret list
|
|
74
|
+
operon config secret set NAME
|
|
75
|
+
operon config secret get NAME
|
|
76
|
+
operon config secret clear NAME
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `path`: prints the resolved file path.
|
|
80
|
+
- `show`: prints the stored document (defaults when the file does not exist).
|
|
81
|
+
It never creates the file. With `--effective` it prints the value that wins
|
|
82
|
+
for every setting, plus where that value comes from; `--json` switches the
|
|
83
|
+
output format.
|
|
84
|
+
- `get`: prints one value and exits `0`; a key without a value prints nothing
|
|
85
|
+
and exits `1`, like `git config`.
|
|
86
|
+
- `set` / `unset`: validate the key and the value before writing, then write
|
|
87
|
+
atomically with user-only permissions. `unset` restores the built-in default.
|
|
88
|
+
- `check`: validates the YAML, warns about a group/world-readable file and
|
|
89
|
+
about unknown keys, fails on secret material, and always prints the effective
|
|
90
|
+
settings — the quickest way to see which layer wins.
|
|
91
|
+
- `init`: writes the default document; refuses to overwrite without `--force`.
|
|
92
|
+
|
|
93
|
+
## Secrets
|
|
94
|
+
|
|
95
|
+
Credentials never live in the user file and never have to live in the
|
|
96
|
+
environment. `operon` stores them through the first available system backend:
|
|
97
|
+
|
|
98
|
+
1. `secret-tool` — the Secret Service (GNOME Keyring, KWallet; `libsecret-tools`).
|
|
99
|
+
2. `systemd-creds --user` — encrypted credentials under
|
|
100
|
+
`$XDG_CONFIG_HOME/operon/secrets/`.
|
|
101
|
+
3. `/usr/bin/security` — the macOS Keychain.
|
|
102
|
+
|
|
103
|
+
All three are used through `subprocess`; no new runtime dependency is required.
|
|
104
|
+
With none of them available, `operon` stops with a clear error and tells you to
|
|
105
|
+
pass `--api-key` or set `NCBI_API_KEY`. The key is resolved as
|
|
106
|
+
`--api-key` > `NCBI_API_KEY` > stored secret.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Store without exposing the value in argv or shell history
|
|
110
|
+
printf '%s' "$NCBI_TOKEN" | operon config secret set ncbi.api_key
|
|
111
|
+
operon config secret list
|
|
112
|
+
operon config secret clear ncbi.api_key
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`secret set` reads the value from stdin, or prompts with hidden input when a
|
|
116
|
+
terminal is attached; the value is never accepted as a command-line argument.
|
|
117
|
+
`secret list` shows backend availability and whether each secret is set — never
|
|
118
|
+
a value. `secret get` prints the value for scripts, with a warning when stdout
|
|
119
|
+
is a terminal.
|
|
120
|
+
|
|
121
|
+
```{note}
|
|
122
|
+
`systemd-creds --user` binds a credential to the user, the machine ID and the
|
|
123
|
+
kernel's boot ID. On a shared HPC home it may therefore not decrypt on another
|
|
124
|
+
node: for remote execution prefer `NCBI_API_KEY` in the environment or
|
|
125
|
+
`--api-key` on the command line.
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Examples
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Fallback identity for containers and cron jobs
|
|
132
|
+
operon config set identity.actor alice
|
|
133
|
+
|
|
134
|
+
# NCBI contact address, then the API key in the secret backend
|
|
135
|
+
operon config set ncbi.email you@example.org
|
|
136
|
+
printf '%s' "$NCBI_TOKEN" | operon config secret set ncbi.api_key
|
|
137
|
+
|
|
138
|
+
# Skip graphics detection for this user without an environment variable
|
|
139
|
+
operon config set ui.splash text
|
|
140
|
+
|
|
141
|
+
# What wins right now, and why
|
|
142
|
+
operon config show --effective
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Environment variables are not deprecated
|
|
146
|
+
|
|
147
|
+
Every variable keeps working and keeps winning over the file. The variables
|
|
148
|
+
`operon` reads directly are audited and documented in
|
|
149
|
+
`tests/unit/test_env_audit.py`: an unannotated `os.environ` read fails that
|
|
150
|
+
test, so any new variable has to be reviewed and documented before it ships.
|
|
151
|
+
Environment capture for `environment_id` (`PROBE_ENV_VARS`) and the HTTP/SSH
|
|
152
|
+
proxy variables read by `requests`/`paramiko` are unaffected.
|