chronaxis 0.1.0.dev0__py3-none-any.whl
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.
- chronaxis/__init__.py +72 -0
- chronaxis/__main__.py +12 -0
- chronaxis/analysis_cli.py +181 -0
- chronaxis/batch/__init__.py +14 -0
- chronaxis/batch/api.py +46 -0
- chronaxis/batch/cli.py +48 -0
- chronaxis/batch/config.py +37 -0
- chronaxis/batch/models.py +202 -0
- chronaxis/batch/process_transport.py +149 -0
- chronaxis/batch/process_tree.py +72 -0
- chronaxis/batch/publication.py +41 -0
- chronaxis/batch/runner.py +236 -0
- chronaxis/batch/templates.py +42 -0
- chronaxis/can_dependencies.py +42 -0
- chronaxis/cli.py +193 -0
- chronaxis/configuration/__init__.py +46 -0
- chronaxis/configuration/cli.py +41 -0
- chronaxis/configuration/diagnostics.py +107 -0
- chronaxis/configuration/explanation.py +233 -0
- chronaxis/configuration/file_tools.py +140 -0
- chronaxis/configuration/imports.py +144 -0
- chronaxis/configuration/initialization.py +36 -0
- chronaxis/configuration/json_parser.py +114 -0
- chronaxis/configuration/models.py +74 -0
- chronaxis/configuration/origins.py +90 -0
- chronaxis/configuration/overrides.py +55 -0
- chronaxis/configuration/resolution.py +150 -0
- chronaxis/configuration/template_catalog.py +68 -0
- chronaxis/configuration/templates/batch/analysis-annotated.yaml +18 -0
- chronaxis/configuration/templates/batch/analysis-minimal.yaml +18 -0
- chronaxis/configuration/templates/batch/annotated.yaml +6 -0
- chronaxis/configuration/templates/batch/minimal.yaml +6 -0
- chronaxis/configuration/templates/can-asc/annotated.yaml +18 -0
- chronaxis/configuration/templates/can-asc/minimal.yaml +18 -0
- chronaxis/configuration/templates/can-blf/annotated.yaml +18 -0
- chronaxis/configuration/templates/can-blf/minimal.yaml +18 -0
- chronaxis/configuration/templates/can-export/annotated.yaml +23 -0
- chronaxis/configuration/templates/can-export/minimal.yaml +23 -0
- chronaxis/configuration/templates/catalog.json +233 -0
- chronaxis/configuration/templates/charge-session/annotated.yaml +38 -0
- chronaxis/configuration/templates/charge-session/minimal.yaml +38 -0
- chronaxis/configuration/templates/command-response/annotated.yaml +32 -0
- chronaxis/configuration/templates/command-response/minimal.yaml +36 -0
- chronaxis/configuration/templates/fault-window/annotated.yaml +25 -0
- chronaxis/configuration/templates/fault-window/minimal.yaml +27 -0
- chronaxis/configuration/templates/ini-mapping/annotated.yaml +20 -0
- chronaxis/configuration/templates/ini-mapping/minimal.yaml +20 -0
- chronaxis/configuration/templates/raw-can-csv/annotated.yaml +34 -0
- chronaxis/configuration/templates/raw-can-csv/minimal.yaml +35 -0
- chronaxis/configuration/templates/shared/charge-session.asc +5 -0
- chronaxis/configuration/templates/shared/command-response.asc +8 -0
- chronaxis/configuration/templates/shared/fault-window.asc +5 -0
- chronaxis/configuration/templates/shared/power.asc +7 -0
- chronaxis/configuration/templates/shared/sample.asc +6 -0
- chronaxis/configuration/templates/shared/sample.blf +0 -0
- chronaxis/configuration/templates/shared/sample.csv +5 -0
- chronaxis/configuration/templates/shared/sample.dbc +11 -0
- chronaxis/configuration/templates/shared/signals.csv +6 -0
- chronaxis/configuration/templates/shared/source.ini +5 -0
- chronaxis/configuration/templates/shared/stability.asc +9 -0
- chronaxis/configuration/templates/shared/teaching.dbc +27 -0
- chronaxis/configuration/templates/shared/threshold.asc +7 -0
- chronaxis/configuration/templates/signal-csv/annotated.yaml +27 -0
- chronaxis/configuration/templates/signal-csv/minimal.yaml +27 -0
- chronaxis/configuration/templates/signal-export/annotated.yaml +27 -0
- chronaxis/configuration/templates/signal-export/minimal.yaml +29 -0
- chronaxis/configuration/templates/stability/annotated.yaml +35 -0
- chronaxis/configuration/templates/stability/minimal.yaml +35 -0
- chronaxis/configuration/templates/threshold/annotated.yaml +22 -0
- chronaxis/configuration/templates/threshold/minimal.yaml +22 -0
- chronaxis/configuration/yaml_parser.py +125 -0
- chronaxis/core/__init__.py +71 -0
- chronaxis/core/binding.py +449 -0
- chronaxis/core/calculation_series_join.py +106 -0
- chronaxis/core/calculations.py +435 -0
- chronaxis/core/calculations_memory_numpy.py +136 -0
- chronaxis/core/calculations_memory_reference.py +165 -0
- chronaxis/core/calculations_numpy.py +298 -0
- chronaxis/core/calculations_reference.py +294 -0
- chronaxis/core/condition_evidence.py +182 -0
- chronaxis/core/conditional_integral_result.py +43 -0
- chronaxis/core/conditional_integral_terms.py +146 -0
- chronaxis/core/conditional_integral_terms_numpy.py +148 -0
- chronaxis/core/conditional_integral_terms_reference.py +111 -0
- chronaxis/core/conditional_time_reduction.py +118 -0
- chronaxis/core/conditional_time_reduction_numpy.py +223 -0
- chronaxis/core/conditional_time_reduction_reference.py +213 -0
- chronaxis/core/declarations.py +192 -0
- chronaxis/core/decoded_binding.py +197 -0
- chronaxis/core/direct_message.py +387 -0
- chronaxis/core/export_interpolation.py +54 -0
- chronaxis/core/expression.py +642 -0
- chronaxis/core/expression_numpy.py +314 -0
- chronaxis/core/expression_reference.py +272 -0
- chronaxis/core/integral_result.py +53 -0
- chronaxis/core/integral_sum.py +77 -0
- chronaxis/core/integral_sum_numpy.py +224 -0
- chronaxis/core/integral_sum_reference.py +148 -0
- chronaxis/core/integral_terms.py +119 -0
- chronaxis/core/integral_terms_numpy.py +127 -0
- chronaxis/core/integral_terms_reference.py +91 -0
- chronaxis/core/mean_weights_numpy.py +29 -0
- chronaxis/core/mean_weights_reference.py +27 -0
- chronaxis/core/message_binding.py +305 -0
- chronaxis/core/models.py +485 -0
- chronaxis/core/normalize_numpy.py +396 -0
- chronaxis/core/numeric.py +472 -0
- chronaxis/core/numeric_numpy.py +440 -0
- chronaxis/core/record_intervals.py +115 -0
- chronaxis/core/sample_reduction.py +161 -0
- chronaxis/core/sample_reduction_numpy.py +160 -0
- chronaxis/core/sample_reduction_reference.py +154 -0
- chronaxis/core/selection.py +74 -0
- chronaxis/core/sequence.py +160 -0
- chronaxis/core/sequence_reference.py +248 -0
- chronaxis/core/stability.py +249 -0
- chronaxis/core/start_end.py +169 -0
- chronaxis/core/state.py +494 -0
- chronaxis/core/state_numpy.py +296 -0
- chronaxis/core/temporal.py +373 -0
- chronaxis/core/temporal_clock.py +25 -0
- chronaxis/core/temporal_memory_numpy.py +163 -0
- chronaxis/core/temporal_memory_reference.py +161 -0
- chronaxis/core/temporal_numpy.py +345 -0
- chronaxis/core/temporal_reference.py +304 -0
- chronaxis/core/time_reduction.py +190 -0
- chronaxis/core/time_reduction_numpy.py +205 -0
- chronaxis/core/time_reduction_reference.py +203 -0
- chronaxis/core/types.py +105 -0
- chronaxis/core/units.py +81 -0
- chronaxis/core/validation.py +94 -0
- chronaxis/core/window_delta.py +123 -0
- chronaxis/core/window_delta_numpy.py +78 -0
- chronaxis/core/window_delta_reference.py +69 -0
- chronaxis/core/windows.py +224 -0
- chronaxis/core/windows_numpy.py +78 -0
- chronaxis/core/windows_reference.py +61 -0
- chronaxis/execution/__init__.py +6 -0
- chronaxis/execution/batch_signal_groups.py +122 -0
- chronaxis/execution/bindings.py +296 -0
- chronaxis/execution/boundaries.py +568 -0
- chronaxis/execution/calculation_blocks.py +338 -0
- chronaxis/execution/calculation_values.py +55 -0
- chronaxis/execution/can_batch_reader.py +356 -0
- chronaxis/execution/can_reader.py +948 -0
- chronaxis/execution/can_reference_template.py +61 -0
- chronaxis/execution/condition_evidence.py +370 -0
- chronaxis/execution/conditional_integral_facts.py +310 -0
- chronaxis/execution/conditional_integral_reduction.py +216 -0
- chronaxis/execution/csv_observation.py +524 -0
- chronaxis/execution/csv_reader.py +662 -0
- chronaxis/execution/current_message_calculation.py +225 -0
- chronaxis/execution/driver_expression.py +274 -0
- chronaxis/execution/expressions.py +618 -0
- chronaxis/execution/frame_capture.py +245 -0
- chronaxis/execution/groups.py +236 -0
- chronaxis/execution/historical_conditional_blocks.py +264 -0
- chronaxis/execution/historical_conditional_integral.py +226 -0
- chronaxis/execution/historical_conditional_time_calculation.py +368 -0
- chronaxis/execution/historical_integral.py +219 -0
- chronaxis/execution/historical_observation.py +372 -0
- chronaxis/execution/historical_sample_calculation.py +338 -0
- chronaxis/execution/historical_selection_rows.py +300 -0
- chronaxis/execution/historical_time_calculation.py +341 -0
- chronaxis/execution/history.py +572 -0
- chronaxis/execution/history_records.py +225 -0
- chronaxis/execution/hold.py +448 -0
- chronaxis/execution/integral_facts.py +311 -0
- chronaxis/execution/integral_reduction.py +216 -0
- chronaxis/execution/legacy_frame_samples.py +94 -0
- chronaxis/execution/memory_reader.py +247 -0
- chronaxis/execution/message_bindings.py +293 -0
- chronaxis/execution/message_delivery.py +37 -0
- chronaxis/execution/observed_ingestion.py +551 -0
- chronaxis/execution/raw_signal_groups.py +192 -0
- chronaxis/execution/record_alarm_duration.py +114 -0
- chronaxis/execution/record_delta_condition.py +167 -0
- chronaxis/execution/record_diagnostics.py +87 -0
- chronaxis/execution/record_event_durations.py +143 -0
- chronaxis/execution/record_export_samples.py +94 -0
- chronaxis/execution/record_exports.py +155 -0
- chronaxis/execution/record_integral.py +196 -0
- chronaxis/execution/record_point_buffer.py +101 -0
- chronaxis/execution/record_rule_timeline.py +344 -0
- chronaxis/execution/record_sample.py +46 -0
- chronaxis/execution/record_sample_series.py +29 -0
- chronaxis/execution/record_scope_calculations.py +290 -0
- chronaxis/execution/record_selection.py +62 -0
- chronaxis/execution/record_sequences.py +199 -0
- chronaxis/execution/record_session_calculations.py +778 -0
- chronaxis/execution/record_signal_export.py +133 -0
- chronaxis/execution/record_source_cursor.py +295 -0
- chronaxis/execution/record_time_calculation.py +322 -0
- chronaxis/execution/record_time_indexes.py +143 -0
- chronaxis/execution/record_value_history.py +160 -0
- chronaxis/execution/record_windows.py +229 -0
- chronaxis/execution/required_expression.py +52 -0
- chronaxis/execution/retained_metadata.py +71 -0
- chronaxis/execution/run_session.py +402 -0
- chronaxis/execution/scanned_signal_proof.py +550 -0
- chronaxis/execution/signal_validity.py +40 -0
- chronaxis/execution/state.py +280 -0
- chronaxis/execution/temporal_buffer.py +508 -0
- chronaxis/execution/text_can_reader.py +359 -0
- chronaxis/execution/timeline.py +309 -0
- chronaxis/execution/timeline_multi.py +415 -0
- chronaxis/execution/window_delta_events.py +220 -0
- chronaxis/execution/window_replay.py +350 -0
- chronaxis/execution/windows.py +173 -0
- chronaxis/guide/README.md +70 -0
- chronaxis/guide/api/AnalysisError.md +14 -0
- chronaxis/guide/api/AnalysisPlan.md +96 -0
- chronaxis/guide/api/AnalysisResult.md +398 -0
- chronaxis/guide/api/AnalysisRunner.md +155 -0
- chronaxis/guide/api/BatchJob.md +19 -0
- chronaxis/guide/api/BatchJobResult.md +61 -0
- chronaxis/guide/api/BatchPlan.md +48 -0
- chronaxis/guide/api/BatchReport.md +108 -0
- chronaxis/guide/api/BatchRunner.md +84 -0
- chronaxis/guide/api/OutputManifest.md +23 -0
- chronaxis/guide/api/PlanFragment.md +47 -0
- chronaxis/guide/api/PlanValidationError.md +98 -0
- chronaxis/guide/api/PresetSpec.md +63 -0
- chronaxis/guide/api/ResultClosedError.md +14 -0
- chronaxis/guide/api/RunMetadata.md +100 -0
- chronaxis/guide/api/TimeConversion.md +29 -0
- chronaxis/guide/api/TimeOverflowError.md +17 -0
- chronaxis/guide/api/build_preset.md +36 -0
- chronaxis/guide/api/checked_add_ns.md +30 -0
- chronaxis/guide/api/convert_time.md +40 -0
- chronaxis/guide/api/explain_analysis_plan.md +38 -0
- chronaxis/guide/api/index.json +185 -0
- chronaxis/guide/api/load_analysis_plan.md +34 -0
- chronaxis/guide/api/load_batch_plan.md +36 -0
- chronaxis/guide/api/parse_datetime_ns.md +35 -0
- chronaxis/guide/api/parse_duration.md +30 -0
- chronaxis/guide/api/resolve_preset_roles.md +37 -0
- chronaxis/guide/api/run_batch.md +38 -0
- chronaxis/guide/api/shift_times_reference.md +33 -0
- chronaxis/guide/api/time_deltas_reference.md +37 -0
- chronaxis/guide/api/validate_analysis_plan.md +38 -0
- chronaxis/guide/en/README.md +74 -0
- chronaxis/guide/en/api/AnalysisError.md +14 -0
- chronaxis/guide/en/api/AnalysisPlan.md +93 -0
- chronaxis/guide/en/api/AnalysisResult.md +398 -0
- chronaxis/guide/en/api/AnalysisRunner.md +191 -0
- chronaxis/guide/en/api/BatchJob.md +17 -0
- chronaxis/guide/en/api/BatchJobResult.md +43 -0
- chronaxis/guide/en/api/BatchPlan.md +37 -0
- chronaxis/guide/en/api/BatchReport.md +52 -0
- chronaxis/guide/en/api/BatchRunner.md +51 -0
- chronaxis/guide/en/api/OutputManifest.md +23 -0
- chronaxis/guide/en/api/PlanFragment.md +33 -0
- chronaxis/guide/en/api/PlanValidationError.md +58 -0
- chronaxis/guide/en/api/PresetSpec.md +51 -0
- chronaxis/guide/en/api/ResultClosedError.md +14 -0
- chronaxis/guide/en/api/RunMetadata.md +100 -0
- chronaxis/guide/en/api/TimeConversion.md +23 -0
- chronaxis/guide/en/api/TimeOverflowError.md +14 -0
- chronaxis/guide/en/api/build_preset.md +23 -0
- chronaxis/guide/en/api/checked_add_ns.md +21 -0
- chronaxis/guide/en/api/convert_time.md +25 -0
- chronaxis/guide/en/api/explain_analysis_plan.md +30 -0
- chronaxis/guide/en/api/index.json +185 -0
- chronaxis/guide/en/api/load_analysis_plan.md +27 -0
- chronaxis/guide/en/api/load_batch_plan.md +28 -0
- chronaxis/guide/en/api/parse_datetime_ns.md +23 -0
- chronaxis/guide/en/api/parse_duration.md +20 -0
- chronaxis/guide/en/api/resolve_preset_roles.md +23 -0
- chronaxis/guide/en/api/run_batch.md +39 -0
- chronaxis/guide/en/api/shift_times_reference.md +21 -0
- chronaxis/guide/en/api/time_deltas_reference.md +22 -0
- chronaxis/guide/en/api/validate_analysis_plan.md +29 -0
- chronaxis/guide/en/fields/analysis/calculations-all-1.json +345 -0
- chronaxis/guide/en/fields/analysis/calculations-all-2.json +300 -0
- chronaxis/guide/en/fields/analysis/calculations-all-3.json +84 -0
- chronaxis/guide/en/fields/analysis/config_version-all-1.json +24 -0
- chronaxis/guide/en/fields/analysis/dataset-all-1.json +344 -0
- chronaxis/guide/en/fields/analysis/derived-all-1.json +147 -0
- chronaxis/guide/en/fields/analysis/diagnostics-all-1.json +69 -0
- chronaxis/guide/en/fields/analysis/execution-all-1.json +167 -0
- chronaxis/guide/en/fields/analysis/imports-all-1.json +39 -0
- chronaxis/guide/en/fields/analysis/intervals-all-1.json +173 -0
- chronaxis/guide/en/fields/analysis/message_calculations-all-1.json +345 -0
- chronaxis/guide/en/fields/analysis/message_calculations-all-2.json +270 -0
- chronaxis/guide/en/fields/analysis/metadata-all-1.json +24 -0
- chronaxis/guide/en/fields/analysis/outputs-all-1.json +332 -0
- chronaxis/guide/en/fields/analysis/outputs-all-2.json +319 -0
- chronaxis/guide/en/fields/analysis/outputs-all-3.json +321 -0
- chronaxis/guide/en/fields/analysis/outputs-all-4.json +236 -0
- chronaxis/guide/en/fields/analysis/outputs-all-5.json +246 -0
- chronaxis/guide/en/fields/analysis/outputs-all-6.json +214 -0
- chronaxis/guide/en/fields/analysis/overrides-all-1.json +104 -0
- chronaxis/guide/en/fields/analysis/presets-charge_session-1.json +398 -0
- chronaxis/guide/en/fields/analysis/presets-charge_session-2.json +114 -0
- chronaxis/guide/en/fields/analysis/presets-command_response-1.json +376 -0
- chronaxis/guide/en/fields/analysis/presets-fault_context-1.json +285 -0
- chronaxis/guide/en/fields/analysis/presets-threshold_excursion-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-condition_duration-1.json +344 -0
- chronaxis/guide/en/fields/analysis/rules-condition_duration-2.json +27 -0
- chronaxis/guide/en/fields/analysis/rules-debounce-1.json +335 -0
- chronaxis/guide/en/fields/analysis/rules-falling_edge-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-hysteresis-1.json +334 -0
- chronaxis/guide/en/fields/analysis/rules-hysteresis-2.json +27 -0
- chronaxis/guide/en/fields/analysis/rules-rising_edge-1.json +317 -0
- chronaxis/guide/en/fields/analysis/rules-start_end-1.json +333 -0
- chronaxis/guide/en/fields/analysis/rules-start_end-2.json +60 -0
- chronaxis/guide/en/fields/analysis/rules-start_only-1.json +334 -0
- chronaxis/guide/en/fields/analysis/rules-window_delta-1.json +338 -0
- chronaxis/guide/en/fields/analysis/rules-window_delta-2.json +96 -0
- chronaxis/guide/en/fields/analysis/sequences-all-1.json +378 -0
- chronaxis/guide/en/fields/analysis/sequences-all-2.json +70 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-1.json +349 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-2.json +297 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-3.json +323 -0
- chronaxis/guide/en/fields/analysis/signals-variant-1-4.json +192 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-1.json +327 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-2.json +312 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-3.json +294 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-4.json +253 -0
- chronaxis/guide/en/fields/analysis/signals-variant-2-5.json +44 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-1.json +318 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-3.json +311 -0
- chronaxis/guide/en/fields/analysis/sources-can_asc-4.json +69 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-1.json +317 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-can_blf-3.json +317 -0
- chronaxis/guide/en/fields/analysis/sources-memory-1.json +332 -0
- chronaxis/guide/en/fields/analysis/sources-memory-2.json +125 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-1.json +330 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-10.json +233 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-11.json +225 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-12.json +228 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-13.json +226 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-14.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-15.json +227 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-16.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-17.json +238 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-18.json +239 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-19.json +233 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-2.json +310 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-20.json +242 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-21.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-22.json +228 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-23.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-24.json +223 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-25.json +290 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-26.json +131 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-3.json +297 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-4.json +226 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-5.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-6.json +227 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-7.json +230 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-8.json +238 -0
- chronaxis/guide/en/fields/analysis/sources-raw_can_csv-9.json +239 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-1.json +331 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-2.json +307 -0
- chronaxis/guide/en/fields/analysis/sources-signal_csv-3.json +315 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-1.json +319 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-2.json +307 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-3.json +312 -0
- chronaxis/guide/en/fields/analysis/sources-variant-6-4.json +113 -0
- chronaxis/guide/en/fields/analysis/windows-all-1.json +361 -0
- chronaxis/guide/en/fields/analysis/windows-all-2.json +187 -0
- chronaxis/guide/en/fields/batch/backend-all-1.json +26 -0
- chronaxis/guide/en/fields/batch/batch_version-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/fail_fast-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/inputs-all-1.json +161 -0
- chronaxis/guide/en/fields/batch/jobs-all-1.json +58 -0
- chronaxis/guide/en/fields/batch/process_count-all-1.json +23 -0
- chronaxis/guide/en/fields/batch/source-all-1.json +22 -0
- chronaxis/guide/en/fields/batch/template-all-1.json +22 -0
- chronaxis/guide/en/fields/definitions/derived-all-1.json +121 -0
- chronaxis/guide/en/fields/definitions/signals-all-1.json +336 -0
- chronaxis/guide/en/fields/definitions/signals-all-2.json +307 -0
- chronaxis/guide/en/fields/definitions/signals-all-3.json +290 -0
- chronaxis/guide/en/fields/definitions/signals-all-4.json +347 -0
- chronaxis/guide/en/fields/definitions/signals-all-5.json +297 -0
- chronaxis/guide/en/fields/definitions/signals-all-6.json +259 -0
- chronaxis/guide/en/fields/definitions/signals-all-7.json +117 -0
- chronaxis/guide/en/fields/definitions/sources-all-1.json +332 -0
- chronaxis/guide/en/fields/definitions/sources-all-10.json +306 -0
- chronaxis/guide/en/fields/definitions/sources-all-11.json +294 -0
- chronaxis/guide/en/fields/definitions/sources-all-12.json +212 -0
- chronaxis/guide/en/fields/definitions/sources-all-13.json +217 -0
- chronaxis/guide/en/fields/definitions/sources-all-14.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-15.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-16.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-17.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-18.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-19.json +213 -0
- chronaxis/guide/en/fields/definitions/sources-all-2.json +323 -0
- chronaxis/guide/en/fields/definitions/sources-all-20.json +217 -0
- chronaxis/guide/en/fields/definitions/sources-all-21.json +210 -0
- chronaxis/guide/en/fields/definitions/sources-all-22.json +214 -0
- chronaxis/guide/en/fields/definitions/sources-all-23.json +218 -0
- chronaxis/guide/en/fields/definitions/sources-all-24.json +209 -0
- chronaxis/guide/en/fields/definitions/sources-all-25.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-26.json +218 -0
- chronaxis/guide/en/fields/definitions/sources-all-27.json +224 -0
- chronaxis/guide/en/fields/definitions/sources-all-28.json +215 -0
- chronaxis/guide/en/fields/definitions/sources-all-29.json +205 -0
- chronaxis/guide/en/fields/definitions/sources-all-3.json +303 -0
- chronaxis/guide/en/fields/definitions/sources-all-30.json +298 -0
- chronaxis/guide/en/fields/definitions/sources-all-31.json +315 -0
- chronaxis/guide/en/fields/definitions/sources-all-32.json +306 -0
- chronaxis/guide/en/fields/definitions/sources-all-33.json +209 -0
- chronaxis/guide/en/fields/definitions/sources-all-4.json +336 -0
- chronaxis/guide/en/fields/definitions/sources-all-5.json +299 -0
- chronaxis/guide/en/fields/definitions/sources-all-6.json +307 -0
- chronaxis/guide/en/fields/definitions/sources-all-7.json +320 -0
- chronaxis/guide/en/fields/definitions/sources-all-8.json +303 -0
- chronaxis/guide/en/fields/definitions/sources-all-9.json +315 -0
- chronaxis/guide/en/fields/index.json +3450 -0
- chronaxis/guide/en/fields/mapping/aliases-all-1.json +91 -0
- chronaxis/guide/en/fields/mapping/analysis-all-1.json +382 -0
- chronaxis/guide/en/fields/mapping/analysis-all-10.json +301 -0
- chronaxis/guide/en/fields/mapping/analysis-all-11.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-12.json +311 -0
- chronaxis/guide/en/fields/mapping/analysis-all-13.json +314 -0
- chronaxis/guide/en/fields/mapping/analysis-all-14.json +310 -0
- chronaxis/guide/en/fields/mapping/analysis-all-15.json +297 -0
- chronaxis/guide/en/fields/mapping/analysis-all-16.json +226 -0
- chronaxis/guide/en/fields/mapping/analysis-all-17.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-18.json +227 -0
- chronaxis/guide/en/fields/mapping/analysis-all-19.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-2.json +323 -0
- chronaxis/guide/en/fields/mapping/analysis-all-20.json +221 -0
- chronaxis/guide/en/fields/mapping/analysis-all-21.json +237 -0
- chronaxis/guide/en/fields/mapping/analysis-all-22.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-23.json +222 -0
- chronaxis/guide/en/fields/mapping/analysis-all-24.json +231 -0
- chronaxis/guide/en/fields/mapping/analysis-all-25.json +225 -0
- chronaxis/guide/en/fields/mapping/analysis-all-26.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-27.json +228 -0
- chronaxis/guide/en/fields/mapping/analysis-all-28.json +230 -0
- chronaxis/guide/en/fields/mapping/analysis-all-29.json +223 -0
- chronaxis/guide/en/fields/mapping/analysis-all-3.json +318 -0
- chronaxis/guide/en/fields/mapping/analysis-all-30.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-31.json +218 -0
- chronaxis/guide/en/fields/mapping/analysis-all-32.json +239 -0
- chronaxis/guide/en/fields/mapping/analysis-all-33.json +233 -0
- chronaxis/guide/en/fields/mapping/analysis-all-34.json +225 -0
- chronaxis/guide/en/fields/mapping/analysis-all-35.json +228 -0
- chronaxis/guide/en/fields/mapping/analysis-all-36.json +226 -0
- chronaxis/guide/en/fields/mapping/analysis-all-37.json +244 -0
- chronaxis/guide/en/fields/mapping/analysis-all-38.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-39.json +299 -0
- chronaxis/guide/en/fields/mapping/analysis-all-4.json +297 -0
- chronaxis/guide/en/fields/mapping/analysis-all-40.json +311 -0
- chronaxis/guide/en/fields/mapping/analysis-all-41.json +310 -0
- chronaxis/guide/en/fields/mapping/analysis-all-42.json +346 -0
- chronaxis/guide/en/fields/mapping/analysis-all-43.json +267 -0
- chronaxis/guide/en/fields/mapping/analysis-all-44.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-45.json +279 -0
- chronaxis/guide/en/fields/mapping/analysis-all-46.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-47.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-48.json +294 -0
- chronaxis/guide/en/fields/mapping/analysis-all-49.json +253 -0
- chronaxis/guide/en/fields/mapping/analysis-all-5.json +312 -0
- chronaxis/guide/en/fields/mapping/analysis-all-50.json +346 -0
- chronaxis/guide/en/fields/mapping/analysis-all-51.json +324 -0
- chronaxis/guide/en/fields/mapping/analysis-all-52.json +335 -0
- chronaxis/guide/en/fields/mapping/analysis-all-53.json +317 -0
- chronaxis/guide/en/fields/mapping/analysis-all-54.json +316 -0
- chronaxis/guide/en/fields/mapping/analysis-all-55.json +302 -0
- chronaxis/guide/en/fields/mapping/analysis-all-56.json +319 -0
- chronaxis/guide/en/fields/mapping/analysis-all-57.json +334 -0
- chronaxis/guide/en/fields/mapping/analysis-all-58.json +333 -0
- chronaxis/guide/en/fields/mapping/analysis-all-59.json +359 -0
- chronaxis/guide/en/fields/mapping/analysis-all-6.json +327 -0
- chronaxis/guide/en/fields/mapping/analysis-all-60.json +303 -0
- chronaxis/guide/en/fields/mapping/analysis-all-61.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-62.json +301 -0
- chronaxis/guide/en/fields/mapping/analysis-all-63.json +326 -0
- chronaxis/guide/en/fields/mapping/analysis-all-64.json +367 -0
- chronaxis/guide/en/fields/mapping/analysis-all-65.json +334 -0
- chronaxis/guide/en/fields/mapping/analysis-all-66.json +358 -0
- chronaxis/guide/en/fields/mapping/analysis-all-67.json +349 -0
- chronaxis/guide/en/fields/mapping/analysis-all-68.json +331 -0
- chronaxis/guide/en/fields/mapping/analysis-all-69.json +304 -0
- chronaxis/guide/en/fields/mapping/analysis-all-7.json +303 -0
- chronaxis/guide/en/fields/mapping/analysis-all-70.json +349 -0
- chronaxis/guide/en/fields/mapping/analysis-all-71.json +288 -0
- chronaxis/guide/en/fields/mapping/analysis-all-72.json +316 -0
- chronaxis/guide/en/fields/mapping/analysis-all-73.json +266 -0
- chronaxis/guide/en/fields/mapping/analysis-all-74.json +227 -0
- chronaxis/guide/en/fields/mapping/analysis-all-75.json +239 -0
- chronaxis/guide/en/fields/mapping/analysis-all-76.json +274 -0
- chronaxis/guide/en/fields/mapping/analysis-all-77.json +380 -0
- chronaxis/guide/en/fields/mapping/analysis-all-78.json +313 -0
- chronaxis/guide/en/fields/mapping/analysis-all-79.json +338 -0
- chronaxis/guide/en/fields/mapping/analysis-all-8.json +292 -0
- chronaxis/guide/en/fields/mapping/analysis-all-80.json +304 -0
- chronaxis/guide/en/fields/mapping/analysis-all-81.json +140 -0
- chronaxis/guide/en/fields/mapping/analysis-all-9.json +332 -0
- chronaxis/guide/en/fields/mapping/io_policy-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/mapping_version-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/path_base-all-1.json +19 -0
- chronaxis/guide/en/fields/mapping/sections-all-1.json +402 -0
- chronaxis/guide/en/fields/mapping/sections-all-2.json +232 -0
- chronaxis/guide/en/semantics.md +70 -0
- chronaxis/guide/en/tasks.json +290 -0
- chronaxis/guide/en/workflow.md +41 -0
- chronaxis/guide/examples/analysis-imports.yaml +22 -0
- chronaxis/guide/examples/analysis.yaml +23 -0
- chronaxis/guide/examples/batch-minimal.yaml +3 -0
- chronaxis/guide/examples/conditional-energy.yaml +36 -0
- chronaxis/guide/examples/data/activity.csv +6 -0
- chronaxis/guide/examples/data/can/activity.asc +11 -0
- chronaxis/guide/examples/data/can/calculation-minimal.asc +6 -0
- chronaxis/guide/examples/data/can/conditional-energy/part-1.asc +92 -0
- chronaxis/guide/examples/data/can/conditional-energy/part-2.asc +36 -0
- chronaxis/guide/examples/data/can/conditional-energy/signals.dbc +10 -0
- chronaxis/guide/examples/data/can/execution-comparison.asc +12 -0
- chronaxis/guide/examples/data/can/execution-report.asc +4 -0
- chronaxis/guide/examples/data/can/expression-extended.asc +11 -0
- chronaxis/guide/examples/data/can/interval-actual.asc +6 -0
- chronaxis/guide/examples/data/can/preset-charge-energy.asc +15 -0
- chronaxis/guide/examples/data/can/preset-charge-minimal.asc +11 -0
- chronaxis/guide/examples/data/can/preset-command-automatic.asc +11 -0
- chronaxis/guide/examples/data/can/preset-fault-context.asc +7 -0
- chronaxis/guide/examples/data/can/preset-threshold-delay.asc +7 -0
- chronaxis/guide/examples/data/can/preset-threshold-partial.asc +7 -0
- chronaxis/guide/examples/data/can/quality.asc +6 -0
- chronaxis/guide/examples/data/can/quickstart-parts/part1.asc +4 -0
- chronaxis/guide/examples/data/can/quickstart-parts/part2.asc +3 -0
- chronaxis/guide/examples/data/can/quickstart.asc +6 -0
- chronaxis/guide/examples/data/can/rule-condition_duration-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-condition_duration-minimal.asc +19 -0
- chronaxis/guide/examples/data/can/rule-debounce-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-falling_edge-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-hysteresis-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-start_end-extended.asc +35 -0
- chronaxis/guide/examples/data/can/rule-start_only-extended.asc +19 -0
- chronaxis/guide/examples/data/can/rule-window_delta-extended.asc +19 -0
- chronaxis/guide/examples/data/can/sequence-outcomes.asc +19 -0
- chronaxis/guide/examples/data/can/signal-types.asc +13 -0
- chronaxis/guide/examples/data/can/start-end.asc +30 -0
- chronaxis/guide/examples/data/can/teaching-base.asc +58 -0
- chronaxis/guide/examples/data/can/teaching.dbc +53 -0
- chronaxis/guide/examples/data/joint-current.csv +5 -0
- chronaxis/guide/examples/data/joint.asc +5 -0
- chronaxis/guide/examples/data/joint.dbc +7 -0
- chronaxis/guide/examples/data/message-clean.asc +6 -0
- chronaxis/guide/examples/data/message-direction.asc +7 -0
- chronaxis/guide/examples/data/message-direction.dbc +7 -0
- chronaxis/guide/examples/data/power.blf +0 -0
- chronaxis/guide/examples/data/power.dbc +6 -0
- chronaxis/guide/examples/data/quality.csv +5 -0
- chronaxis/guide/examples/data/raw-can-example.csv +5 -0
- chronaxis/guide/examples/data/signal-types.csv +5 -0
- chronaxis/guide/examples/data/signals.csv +6 -0
- chronaxis/guide/examples/data/timing.asc +6 -0
- chronaxis/guide/examples/data/timing.dbc +11 -0
- chronaxis/guide/examples/export-can-minimal.yaml +24 -0
- chronaxis/guide/examples/input-csv-minimal.yaml +23 -0
- chronaxis/guide/examples/preset-charge-energy.yaml +41 -0
- chronaxis/guide/examples/preset-charge-minimal.yaml +31 -0
- chronaxis/guide/examples/preset-fault-context.yaml +27 -0
- chronaxis/guide/examples/quality.yaml +19 -0
- chronaxis/guide/examples/sequence-outcomes.yaml +39 -0
- chronaxis/guide/examples/shared/definitions.yaml +14 -0
- chronaxis/guide/examples/signal-enum-minimal.yaml +19 -0
- chronaxis/guide/examples/signal-number-conversion.yaml +24 -0
- chronaxis/guide/examples/window-merged.yaml +28 -0
- chronaxis/guide/fields/analysis/calculations-all-1.json +360 -0
- chronaxis/guide/fields/analysis/calculations-all-2.json +299 -0
- chronaxis/guide/fields/analysis/calculations-all-3.json +70 -0
- chronaxis/guide/fields/analysis/config_version-all-1.json +24 -0
- chronaxis/guide/fields/analysis/dataset-all-1.json +344 -0
- chronaxis/guide/fields/analysis/derived-all-1.json +147 -0
- chronaxis/guide/fields/analysis/diagnostics-all-1.json +69 -0
- chronaxis/guide/fields/analysis/execution-all-1.json +167 -0
- chronaxis/guide/fields/analysis/imports-all-1.json +39 -0
- chronaxis/guide/fields/analysis/intervals-all-1.json +173 -0
- chronaxis/guide/fields/analysis/message_calculations-all-1.json +360 -0
- chronaxis/guide/fields/analysis/message_calculations-all-2.json +255 -0
- chronaxis/guide/fields/analysis/metadata-all-1.json +24 -0
- chronaxis/guide/fields/analysis/outputs-all-1.json +349 -0
- chronaxis/guide/fields/analysis/outputs-all-2.json +302 -0
- chronaxis/guide/fields/analysis/outputs-all-3.json +321 -0
- chronaxis/guide/fields/analysis/outputs-all-4.json +253 -0
- chronaxis/guide/fields/analysis/outputs-all-5.json +244 -0
- chronaxis/guide/fields/analysis/outputs-all-6.json +199 -0
- chronaxis/guide/fields/analysis/overrides-all-1.json +104 -0
- chronaxis/guide/fields/analysis/presets-charge_session-1.json +398 -0
- chronaxis/guide/fields/analysis/presets-charge_session-2.json +114 -0
- chronaxis/guide/fields/analysis/presets-command_response-1.json +376 -0
- chronaxis/guide/fields/analysis/presets-fault_context-1.json +285 -0
- chronaxis/guide/fields/analysis/presets-threshold_excursion-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-condition_duration-1.json +344 -0
- chronaxis/guide/fields/analysis/rules-condition_duration-2.json +27 -0
- chronaxis/guide/fields/analysis/rules-debounce-1.json +335 -0
- chronaxis/guide/fields/analysis/rules-falling_edge-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-hysteresis-1.json +334 -0
- chronaxis/guide/fields/analysis/rules-hysteresis-2.json +27 -0
- chronaxis/guide/fields/analysis/rules-rising_edge-1.json +317 -0
- chronaxis/guide/fields/analysis/rules-start_end-1.json +349 -0
- chronaxis/guide/fields/analysis/rules-start_end-2.json +44 -0
- chronaxis/guide/fields/analysis/rules-start_only-1.json +334 -0
- chronaxis/guide/fields/analysis/rules-window_delta-1.json +356 -0
- chronaxis/guide/fields/analysis/rules-window_delta-2.json +78 -0
- chronaxis/guide/fields/analysis/sequences-all-1.json +394 -0
- chronaxis/guide/fields/analysis/sequences-all-2.json +54 -0
- chronaxis/guide/fields/analysis/signals-variant-1-1.json +349 -0
- chronaxis/guide/fields/analysis/signals-variant-1-2.json +297 -0
- chronaxis/guide/fields/analysis/signals-variant-1-3.json +340 -0
- chronaxis/guide/fields/analysis/signals-variant-1-4.json +175 -0
- chronaxis/guide/fields/analysis/signals-variant-2-1.json +327 -0
- chronaxis/guide/fields/analysis/signals-variant-2-2.json +335 -0
- chronaxis/guide/fields/analysis/signals-variant-2-3.json +289 -0
- chronaxis/guide/fields/analysis/signals-variant-2-4.json +270 -0
- chronaxis/guide/fields/analysis/sources-can_asc-1.json +318 -0
- chronaxis/guide/fields/analysis/sources-can_asc-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-can_asc-3.json +311 -0
- chronaxis/guide/fields/analysis/sources-can_asc-4.json +69 -0
- chronaxis/guide/fields/analysis/sources-can_blf-1.json +317 -0
- chronaxis/guide/fields/analysis/sources-can_blf-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-can_blf-3.json +317 -0
- chronaxis/guide/fields/analysis/sources-memory-1.json +347 -0
- chronaxis/guide/fields/analysis/sources-memory-2.json +110 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-1.json +330 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-10.json +233 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-11.json +225 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-12.json +228 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-13.json +226 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-14.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-15.json +227 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-16.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-17.json +238 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-18.json +239 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-19.json +233 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-2.json +310 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-20.json +242 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-21.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-22.json +228 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-23.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-24.json +223 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-25.json +290 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-26.json +131 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-3.json +297 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-4.json +226 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-5.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-6.json +227 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-7.json +230 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-8.json +238 -0
- chronaxis/guide/fields/analysis/sources-raw_can_csv-9.json +239 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-1.json +331 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-2.json +327 -0
- chronaxis/guide/fields/analysis/sources-signal_csv-3.json +295 -0
- chronaxis/guide/fields/analysis/sources-variant-6-1.json +319 -0
- chronaxis/guide/fields/analysis/sources-variant-6-2.json +327 -0
- chronaxis/guide/fields/analysis/sources-variant-6-3.json +314 -0
- chronaxis/guide/fields/analysis/sources-variant-6-4.json +91 -0
- chronaxis/guide/fields/analysis/windows-all-1.json +361 -0
- chronaxis/guide/fields/analysis/windows-all-2.json +187 -0
- chronaxis/guide/fields/batch/backend-all-1.json +26 -0
- chronaxis/guide/fields/batch/batch_version-all-1.json +22 -0
- chronaxis/guide/fields/batch/fail_fast-all-1.json +22 -0
- chronaxis/guide/fields/batch/inputs-all-1.json +161 -0
- chronaxis/guide/fields/batch/jobs-all-1.json +58 -0
- chronaxis/guide/fields/batch/process_count-all-1.json +23 -0
- chronaxis/guide/fields/batch/source-all-1.json +22 -0
- chronaxis/guide/fields/batch/template-all-1.json +22 -0
- chronaxis/guide/fields/definitions/derived-all-1.json +121 -0
- chronaxis/guide/fields/definitions/signals-all-1.json +336 -0
- chronaxis/guide/fields/definitions/signals-all-2.json +307 -0
- chronaxis/guide/fields/definitions/signals-all-3.json +305 -0
- chronaxis/guide/fields/definitions/signals-all-4.json +352 -0
- chronaxis/guide/fields/definitions/signals-all-5.json +311 -0
- chronaxis/guide/fields/definitions/signals-all-6.json +254 -0
- chronaxis/guide/fields/definitions/signals-all-7.json +88 -0
- chronaxis/guide/fields/definitions/sources-all-1.json +332 -0
- chronaxis/guide/fields/definitions/sources-all-10.json +307 -0
- chronaxis/guide/fields/definitions/sources-all-11.json +280 -0
- chronaxis/guide/fields/definitions/sources-all-12.json +209 -0
- chronaxis/guide/fields/definitions/sources-all-13.json +219 -0
- chronaxis/guide/fields/definitions/sources-all-14.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-15.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-16.json +232 -0
- chronaxis/guide/fields/definitions/sources-all-17.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-18.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-19.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-2.json +336 -0
- chronaxis/guide/fields/definitions/sources-all-20.json +228 -0
- chronaxis/guide/fields/definitions/sources-all-21.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-22.json +232 -0
- chronaxis/guide/fields/definitions/sources-all-23.json +213 -0
- chronaxis/guide/fields/definitions/sources-all-24.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-25.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-26.json +228 -0
- chronaxis/guide/fields/definitions/sources-all-27.json +212 -0
- chronaxis/guide/fields/definitions/sources-all-28.json +217 -0
- chronaxis/guide/fields/definitions/sources-all-29.json +227 -0
- chronaxis/guide/fields/definitions/sources-all-3.json +306 -0
- chronaxis/guide/fields/definitions/sources-all-30.json +333 -0
- chronaxis/guide/fields/definitions/sources-all-31.json +302 -0
- chronaxis/guide/fields/definitions/sources-all-32.json +319 -0
- chronaxis/guide/fields/definitions/sources-all-33.json +89 -0
- chronaxis/guide/fields/definitions/sources-all-4.json +336 -0
- chronaxis/guide/fields/definitions/sources-all-5.json +313 -0
- chronaxis/guide/fields/definitions/sources-all-6.json +292 -0
- chronaxis/guide/fields/definitions/sources-all-7.json +319 -0
- chronaxis/guide/fields/definitions/sources-all-8.json +315 -0
- chronaxis/guide/fields/definitions/sources-all-9.json +318 -0
- chronaxis/guide/fields/index.json +3432 -0
- chronaxis/guide/fields/mapping/aliases-all-1.json +91 -0
- chronaxis/guide/fields/mapping/analysis-all-1.json +382 -0
- chronaxis/guide/fields/mapping/analysis-all-10.json +307 -0
- chronaxis/guide/fields/mapping/analysis-all-11.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-12.json +329 -0
- chronaxis/guide/fields/mapping/analysis-all-13.json +294 -0
- chronaxis/guide/fields/mapping/analysis-all-14.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-15.json +280 -0
- chronaxis/guide/fields/mapping/analysis-all-16.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-17.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-18.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-19.json +237 -0
- chronaxis/guide/fields/mapping/analysis-all-2.json +342 -0
- chronaxis/guide/fields/mapping/analysis-all-20.json +233 -0
- chronaxis/guide/fields/mapping/analysis-all-21.json +244 -0
- chronaxis/guide/fields/mapping/analysis-all-22.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-23.json +226 -0
- chronaxis/guide/fields/mapping/analysis-all-24.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-25.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-26.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-27.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-28.json +237 -0
- chronaxis/guide/fields/mapping/analysis-all-29.json +233 -0
- chronaxis/guide/fields/mapping/analysis-all-3.json +322 -0
- chronaxis/guide/fields/mapping/analysis-all-30.json +244 -0
- chronaxis/guide/fields/mapping/analysis-all-31.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-32.json +226 -0
- chronaxis/guide/fields/mapping/analysis-all-33.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-34.json +227 -0
- chronaxis/guide/fields/mapping/analysis-all-35.json +230 -0
- chronaxis/guide/fields/mapping/analysis-all-36.json +221 -0
- chronaxis/guide/fields/mapping/analysis-all-37.json +291 -0
- chronaxis/guide/fields/mapping/analysis-all-38.json +315 -0
- chronaxis/guide/fields/mapping/analysis-all-39.json +304 -0
- chronaxis/guide/fields/mapping/analysis-all-4.json +312 -0
- chronaxis/guide/fields/mapping/analysis-all-40.json +307 -0
- chronaxis/guide/fields/mapping/analysis-all-41.json +292 -0
- chronaxis/guide/fields/mapping/analysis-all-42.json +333 -0
- chronaxis/guide/fields/mapping/analysis-all-43.json +296 -0
- chronaxis/guide/fields/mapping/analysis-all-44.json +322 -0
- chronaxis/guide/fields/mapping/analysis-all-45.json +298 -0
- chronaxis/guide/fields/mapping/analysis-all-46.json +347 -0
- chronaxis/guide/fields/mapping/analysis-all-47.json +302 -0
- chronaxis/guide/fields/mapping/analysis-all-48.json +263 -0
- chronaxis/guide/fields/mapping/analysis-all-49.json +301 -0
- chronaxis/guide/fields/mapping/analysis-all-5.json +313 -0
- chronaxis/guide/fields/mapping/analysis-all-50.json +336 -0
- chronaxis/guide/fields/mapping/analysis-all-51.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-52.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-53.json +334 -0
- chronaxis/guide/fields/mapping/analysis-all-54.json +339 -0
- chronaxis/guide/fields/mapping/analysis-all-55.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-56.json +336 -0
- chronaxis/guide/fields/mapping/analysis-all-57.json +335 -0
- chronaxis/guide/fields/mapping/analysis-all-58.json +333 -0
- chronaxis/guide/fields/mapping/analysis-all-59.json +325 -0
- chronaxis/guide/fields/mapping/analysis-all-6.json +323 -0
- chronaxis/guide/fields/mapping/analysis-all-60.json +334 -0
- chronaxis/guide/fields/mapping/analysis-all-61.json +311 -0
- chronaxis/guide/fields/mapping/analysis-all-62.json +289 -0
- chronaxis/guide/fields/mapping/analysis-all-63.json +383 -0
- chronaxis/guide/fields/mapping/analysis-all-64.json +357 -0
- chronaxis/guide/fields/mapping/analysis-all-65.json +375 -0
- chronaxis/guide/fields/mapping/analysis-all-66.json +351 -0
- chronaxis/guide/fields/mapping/analysis-all-67.json +346 -0
- chronaxis/guide/fields/mapping/analysis-all-68.json +317 -0
- chronaxis/guide/fields/mapping/analysis-all-69.json +313 -0
- chronaxis/guide/fields/mapping/analysis-all-7.json +306 -0
- chronaxis/guide/fields/mapping/analysis-all-70.json +326 -0
- chronaxis/guide/fields/mapping/analysis-all-71.json +316 -0
- chronaxis/guide/fields/mapping/analysis-all-72.json +264 -0
- chronaxis/guide/fields/mapping/analysis-all-73.json +228 -0
- chronaxis/guide/fields/mapping/analysis-all-74.json +241 -0
- chronaxis/guide/fields/mapping/analysis-all-75.json +273 -0
- chronaxis/guide/fields/mapping/analysis-all-76.json +382 -0
- chronaxis/guide/fields/mapping/analysis-all-77.json +328 -0
- chronaxis/guide/fields/mapping/analysis-all-78.json +338 -0
- chronaxis/guide/fields/mapping/analysis-all-79.json +304 -0
- chronaxis/guide/fields/mapping/analysis-all-8.json +309 -0
- chronaxis/guide/fields/mapping/analysis-all-80.json +140 -0
- chronaxis/guide/fields/mapping/analysis-all-9.json +329 -0
- chronaxis/guide/fields/mapping/io_policy-all-1.json +19 -0
- chronaxis/guide/fields/mapping/mapping_version-all-1.json +19 -0
- chronaxis/guide/fields/mapping/path_base-all-1.json +19 -0
- chronaxis/guide/fields/mapping/sections-all-1.json +402 -0
- chronaxis/guide/fields/mapping/sections-all-2.json +232 -0
- chronaxis/guide/lookup.py +90 -0
- chronaxis/guide/manifest.json +614 -0
- chronaxis/guide/run_analysis.py +34 -0
- chronaxis/guide/schemas/analysis.schema.json +8451 -0
- chronaxis/guide/schemas/batch-v1.schema.json +172 -0
- chronaxis/guide/schemas/definitions.schema.json +29 -0
- chronaxis/guide/schemas/legacy-import-v1.schema.json +143 -0
- chronaxis/guide/semantics.md +62 -0
- chronaxis/guide/tasks.json +290 -0
- chronaxis/guide/workflow.md +38 -0
- chronaxis/legacy/__init__.py +46 -0
- chronaxis/legacy/batch_read.py +412 -0
- chronaxis/legacy/batch_validation.py +134 -0
- chronaxis/legacy/batch_wire.py +264 -0
- chronaxis/legacy/batch_worker.py +417 -0
- chronaxis/legacy/binding.py +154 -0
- chronaxis/legacy/dbc_cycles.py +47 -0
- chronaxis/legacy/decode_policy.py +28 -0
- chronaxis/legacy/disjunction.py +79 -0
- chronaxis/legacy/export_worker.py +147 -0
- chronaxis/legacy/export_write.py +378 -0
- chronaxis/legacy/message_store.py +562 -0
- chronaxis/legacy/process_read.py +526 -0
- chronaxis/legacy/raw_store.py +341 -0
- chronaxis/legacy/records.py +709 -0
- chronaxis/legacy/required_records.py +122 -0
- chronaxis/legacy/sum.py +403 -0
- chronaxis/legacy/sum_numpy.py +43 -0
- chronaxis/legacy/updates.py +277 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/can_processor.py +138 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/file_processor.py +218 -0
- chronaxis/legacy/vendor/sclicer_functions_v1/utils.py +447 -0
- chronaxis/legacy/worker.py +352 -0
- chronaxis/migration/__init__.py +11 -0
- chronaxis/migration/api.py +270 -0
- chronaxis/migration/ini.py +110 -0
- chronaxis/migration/legacy_sum.py +304 -0
- chronaxis/migration/models.py +83 -0
- chronaxis/migration/publication.py +230 -0
- chronaxis/migration/sclicer.py +241 -0
- chronaxis/migration/slope.py +78 -0
- chronaxis/migration/start_end.py +48 -0
- chronaxis/planning/__init__.py +19 -0
- chronaxis/planning/channels.py +30 -0
- chronaxis/planning/checks.py +447 -0
- chronaxis/planning/config_groups.py +215 -0
- chronaxis/planning/dbc_defaults.py +88 -0
- chronaxis/planning/export_options.py +247 -0
- chronaxis/planning/input_defaults.py +62 -0
- chronaxis/planning/input_paths.py +124 -0
- chronaxis/planning/input_requirements.py +250 -0
- chronaxis/planning/inputs.py +306 -0
- chronaxis/planning/intervals.py +242 -0
- chronaxis/planning/legacy_execution.py +38 -0
- chronaxis/planning/message_calculations.py +171 -0
- chronaxis/planning/models.py +369 -0
- chronaxis/planning/nodes.py +355 -0
- chronaxis/planning/plan.py +294 -0
- chronaxis/planning/preset_models.py +211 -0
- chronaxis/planning/record_execution.py +76 -0
- chronaxis/planning/reports.py +523 -0
- chronaxis/planning/sequences.py +91 -0
- chronaxis/planning/signal_groups.py +61 -0
- chronaxis/planning/signal_validity.py +46 -0
- chronaxis/planning/text_inputs.py +110 -0
- chronaxis/presets.py +270 -0
- chronaxis/results/__init__.py +34 -0
- chronaxis/results/analysis_outcome.py +67 -0
- chronaxis/results/artifact_exports.py +212 -0
- chronaxis/results/binding_metadata.py +54 -0
- chronaxis/results/budget.py +138 -0
- chronaxis/results/can_metadata.py +247 -0
- chronaxis/results/codec.py +246 -0
- chronaxis/results/errors.py +25 -0
- chronaxis/results/export_files.py +216 -0
- chronaxis/results/frame_exports.py +299 -0
- chronaxis/results/frame_patch.py +186 -0
- chronaxis/results/frame_rebuild.py +458 -0
- chronaxis/results/frame_sort.py +223 -0
- chronaxis/results/input_diagnostics.py +51 -0
- chronaxis/results/manifest.py +343 -0
- chronaxis/results/merge_runs.py +207 -0
- chronaxis/results/owned_directory.py +32 -0
- chronaxis/results/raw_exports.py +689 -0
- chronaxis/results/readable.py +355 -0
- chronaxis/results/readable_format.py +94 -0
- chronaxis/results/result.py +734 -0
- chronaxis/results/rows.py +57 -0
- chronaxis/results/signal_exports.py +209 -0
- chronaxis/results/signal_grid.py +219 -0
- chronaxis/results/spool.py +421 -0
- chronaxis/results/summary.py +350 -0
- chronaxis/results/text_can_metadata.py +64 -0
- chronaxis/results/threshold_metadata.py +105 -0
- chronaxis/runner.py +121 -0
- chronaxis/sources/__init__.py +23 -0
- chronaxis/sources/asc.py +412 -0
- chronaxis/sources/blf.py +101 -0
- chronaxis/sources/can_spec.py +179 -0
- chronaxis/sources/can_updates.py +160 -0
- chronaxis/sources/csv_spec.py +133 -0
- chronaxis/sources/descriptions.py +65 -0
- chronaxis/sources/memory.py +299 -0
- chronaxis/sources/models.py +497 -0
- chronaxis/sources/packing.py +170 -0
- chronaxis/sources/protocol.py +221 -0
- chronaxis/sources/raw_can.py +62 -0
- chronaxis/sources/raw_csv.py +470 -0
- chronaxis/sources/raw_csv_layout.py +310 -0
- chronaxis/sources/signal_csv.py +608 -0
- chronaxis/sources/text_can_decode.py +421 -0
- chronaxis/sources/text_can_ref.py +48 -0
- chronaxis/sources/text_can_spec.py +61 -0
- chronaxis/timebase/__init__.py +19 -0
- chronaxis/timebase/conversion.py +364 -0
- chronaxis/timebase/numpy_ops.py +104 -0
- chronaxis/user_guide.py +81 -0
- chronaxis-0.1.0.dev0.dist-info/METADATA +172 -0
- chronaxis-0.1.0.dev0.dist-info/RECORD +917 -0
- chronaxis-0.1.0.dev0.dist-info/WHEEL +5 -0
- chronaxis-0.1.0.dev0.dist-info/entry_points.txt +2 -0
- chronaxis-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
- chronaxis-0.1.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""当前配置的格式转换和新文件发布;不推断业务参数,不执行分析。"""
|
|
2
|
+
from io import StringIO
|
|
3
|
+
import json
|
|
4
|
+
import math
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from . import load_configuration, parse_configuration
|
|
8
|
+
from .diagnostics import locate_error
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def configuration_type(data):
|
|
12
|
+
"""识别三个独立当前入口。参数: 原生配置。返回: analysis/batch/mapping。异常: ValueError。
|
|
13
|
+
|
|
14
|
+
版本不能猜测或迁移;旧INI由独立legacy import入口处理。
|
|
15
|
+
"""
|
|
16
|
+
from ..planning.checks import PlanValidationError
|
|
17
|
+
versions={'config_version':('analysis',3),'batch_version':('batch',1),'mapping_version':('mapping',1)}
|
|
18
|
+
present=[key for key in versions if type(data) is dict and key in data]
|
|
19
|
+
if len(present)!=1:raise PlanValidationError('$','需要且只能有一种配置版本字段','invalid_version')
|
|
20
|
+
key=present[0];name,version=versions[key]
|
|
21
|
+
if type(data[key]) is not int or data[key]!=version:
|
|
22
|
+
raise PlanValidationError('$.'+key,'仅接受当前版本'+str(version)+',不转换旧结构','invalid_version')
|
|
23
|
+
return name
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def validate_document(document, base, *, return_plan=False):
|
|
27
|
+
"""调用现有模型;return_plan=True时同时返回计划,避免配置工具重复加载DBC。
|
|
28
|
+
|
|
29
|
+
批量不加载子任务,映射只核映射与其分析部分;INI模式与段名需在实际导入时核对。
|
|
30
|
+
"""
|
|
31
|
+
from ..planning import AnalysisPlan
|
|
32
|
+
from ..planning.checks import PlanValidationError
|
|
33
|
+
from .imports import expand_document_imports
|
|
34
|
+
try:
|
|
35
|
+
document=expand_document_imports(document)
|
|
36
|
+
name=configuration_type(document.data)
|
|
37
|
+
if name=='analysis':plan=AnalysisPlan.from_dict(document.data,base_dir=base)
|
|
38
|
+
elif name=='batch':
|
|
39
|
+
from ..batch.models import BatchPlan
|
|
40
|
+
plan=BatchPlan.from_dict(document.data,base_dir=base)
|
|
41
|
+
else:
|
|
42
|
+
from ..migration.api import _prepare_mapping
|
|
43
|
+
from ..migration.ini import ImportProblem
|
|
44
|
+
try:_prepare_mapping(document.data,base)
|
|
45
|
+
except ImportProblem as error:
|
|
46
|
+
raise PlanValidationError(error.issue.path,error.issue.message,error.issue.code) from error
|
|
47
|
+
try:plan=AnalysisPlan.from_dict(document.data['analysis'],base_dir=base)
|
|
48
|
+
except PlanValidationError as error:
|
|
49
|
+
error.path='$.analysis'+error.path[1:];error.refresh_text();raise
|
|
50
|
+
return (name,plan) if return_plan else name
|
|
51
|
+
except PlanValidationError as error:raise locate_error(error,document)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def path_fields(data, config_type):
|
|
55
|
+
"""枚举声明的文件路径位置。参数: 已校验配置及类型。返回: (容器,键)迭代器。异常: 内部结构错误。
|
|
56
|
+
|
|
57
|
+
只认来源文件/DBC、批量子计划和公共定义;metadata与表达式中的path文字保持原样。
|
|
58
|
+
"""
|
|
59
|
+
if config_type=='batch':
|
|
60
|
+
for job in data.get('jobs',[]):yield job,'plan'
|
|
61
|
+
if 'template' in data:
|
|
62
|
+
yield data,'template'
|
|
63
|
+
from ..planning.input_paths import source_path_fields
|
|
64
|
+
holder={'paths':data['inputs']}
|
|
65
|
+
for owner,key in source_path_fields(holder):
|
|
66
|
+
yield (data,'inputs') if owner is holder else (owner,key)
|
|
67
|
+
return
|
|
68
|
+
analysis=data['analysis'] if config_type=='mapping' else data
|
|
69
|
+
for source in analysis.get('sources',[]):
|
|
70
|
+
from ..planning.input_paths import source_path_fields
|
|
71
|
+
yield from source_path_fields(source)
|
|
72
|
+
for channel in source.get('dbc_by_channel',{}):yield source['dbc_by_channel'],channel
|
|
73
|
+
for index in range(len(analysis.get('imports',[]))):yield analysis['imports'],index
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def same_native_value(left,right):
|
|
77
|
+
"""核类型/顺序/数值不漂移,包含负零和大整数。参数: 原生值。返回: bool。异常: 无。"""
|
|
78
|
+
if type(left) is not type(right):return False
|
|
79
|
+
if type(left) is dict:
|
|
80
|
+
return list(left)==list(right) and all(same_native_value(left[key],right[key]) for key in left)
|
|
81
|
+
if type(left) is list:
|
|
82
|
+
return len(left)==len(right) and all(same_native_value(a,b) for a,b in zip(left,right))
|
|
83
|
+
if type(left) is float and left==0:return left==right and math.copysign(1,left)==math.copysign(1,right)
|
|
84
|
+
return left==right
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def serialize_configuration(data, format):
|
|
88
|
+
"""输出可被受限解析器再读取的文本。参数: 配置及json/yaml。返回: str。异常: ValueError。
|
|
89
|
+
|
|
90
|
+
输出后独立重解析并核类型和值,避免YAML隐式类型或浮点表示改写含义。注释不参与互转。
|
|
91
|
+
"""
|
|
92
|
+
if format=='json':text=json.dumps(data,ensure_ascii=False,allow_nan=False,indent=2)+'\n'
|
|
93
|
+
elif format=='yaml':
|
|
94
|
+
from ruamel.yaml import YAML
|
|
95
|
+
yaml=YAML(typ='safe',pure=True);yaml.version=(1,2);yaml.default_flow_style=False
|
|
96
|
+
yaml.sort_base_mapping_type_on_output=False
|
|
97
|
+
yaml.representer.ignore_aliases=lambda value:True
|
|
98
|
+
stream=StringIO();yaml.dump(data,stream);text=stream.getvalue()
|
|
99
|
+
else:raise ValueError('输出格式仅支持json或yaml')
|
|
100
|
+
if not same_native_value(data,parse_configuration(text,format=format).data):
|
|
101
|
+
raise ValueError('格式转换不能保持原配置类型、顺序和值;未写文件')
|
|
102
|
+
return text
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def output_format(path):
|
|
106
|
+
"""由扩展名选择格式。参数: Path。返回: json/yaml。异常: ValueError。"""
|
|
107
|
+
suffix=path.suffix.lower()
|
|
108
|
+
if suffix not in ('.json','.yaml','.yml'):raise ValueError('新文件需要.json、.yaml或.yml扩展名')
|
|
109
|
+
return 'json' if suffix=='.json' else 'yaml'
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def write_new_configuration(path, text):
|
|
113
|
+
"""独占写新文件。参数: 路径及已校验文本。返回: Path。异常: IO/取消。
|
|
114
|
+
|
|
115
|
+
已存在文件、硬链接和符号链接都由独占打开拒绝;部分写失败仅清理本次创建的文件。
|
|
116
|
+
"""
|
|
117
|
+
target=Path(path).absolute()
|
|
118
|
+
stream=target.open('x',encoding='utf-8',newline='\n')
|
|
119
|
+
try:
|
|
120
|
+
with stream:stream.write(text);stream.flush()
|
|
121
|
+
except BaseException as error:
|
|
122
|
+
try:stream.close()
|
|
123
|
+
except OSError as cleanup:error.add_note('未能关闭部分配置 '+str(target)+': '+str(cleanup))
|
|
124
|
+
try:target.unlink()
|
|
125
|
+
except OSError as cleanup:error.add_note('未能清理部分配置 '+str(target)+': '+str(cleanup))
|
|
126
|
+
raise
|
|
127
|
+
return target
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def convert_configuration(source, output):
|
|
131
|
+
"""仅改变当前配置的JSON/YAML表示。参数: 输入、新文件。返回: 输出Path。异常: 配置/IO错误。
|
|
132
|
+
|
|
133
|
+
相对路径存在时只允许同目录输出;跨目录需使用resolve显式重定位,不静默修改原值。
|
|
134
|
+
"""
|
|
135
|
+
source=Path(source).absolute();target=Path(output).absolute()
|
|
136
|
+
document=load_configuration(source);name=validate_document(document,source.parent)
|
|
137
|
+
if source.parent!=target.parent and any(not Path(owner[key]).is_absolute() for owner,key in path_fields(document.data,name)):
|
|
138
|
+
raise ValueError('配置含相对路径,convert只能写入同目录;跨目录请用config resolve --output重新定位')
|
|
139
|
+
text=serialize_configuration(document.data,output_format(target))
|
|
140
|
+
return write_new_configuration(target,text)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""展开明确列出的一层本地公共定义,供分析文件和INI映射文件加载使用。
|
|
2
|
+
|
|
3
|
+
主配置按imports顺序引入sources/signals/derived,最后追加本地声明;重复名称
|
|
4
|
+
直接拒绝。导入文件不能再导入文件,也不能声明运行、规则或输出字段。
|
|
5
|
+
仅打开配置文件,数据/DBC路径按各自声明文件转为词法绝对路径;不读取业务输入。
|
|
6
|
+
位置随本次加载保留,成功计划不持有原文或第二份配置,不执行环境替换或模板。
|
|
7
|
+
"""
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from types import MappingProxyType
|
|
11
|
+
|
|
12
|
+
from . import load_configuration
|
|
13
|
+
from .diagnostics import locate_error
|
|
14
|
+
from .models import ConfigurationDocument, ConfigurationOrigin, field_path_text
|
|
15
|
+
|
|
16
|
+
SECTIONS=('sources','signals','derived') # 唯一允许共享的定义,不包含执行节点。
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _reject(document, path, message, code='invalid_import', hint=None):
|
|
20
|
+
"""在实际声明处拒绝导入。参数: 文档、tuple路径、原因/代码/建议。返回: 不返回。异常: PlanValidationError。"""
|
|
21
|
+
from ..planning.checks import PlanValidationError
|
|
22
|
+
raise locate_error(PlanValidationError(field_path_text(path),message,code,hint=hint),document)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _source_paths(source, base, path, document):
|
|
26
|
+
"""固定一项来源中的公开文件路径。参数: 来源副本、声明目录、字段路径、原文档。返回: None。异常: 字段错误。
|
|
27
|
+
|
|
28
|
+
只改本次副本,metadata内任意path不解释为文件;不调用stat或resolve。
|
|
29
|
+
"""
|
|
30
|
+
from ..planning.checks import absolute_path, array_at, PlanValidationError
|
|
31
|
+
try:
|
|
32
|
+
# 路径文字、列表和带offset的文件对象共用路径定位,不展开输入目录。
|
|
33
|
+
from ..planning.input_paths import source_path_fields
|
|
34
|
+
for owner,key in source_path_fields(source,field_path_text(path)):
|
|
35
|
+
owner[key]=str(absolute_path(owner[key],base,field_path_text((*path,key))))
|
|
36
|
+
if 'dbc_by_channel' in source:
|
|
37
|
+
values=source['dbc_by_channel']
|
|
38
|
+
if type(values) is not dict:
|
|
39
|
+
_reject(document,(*path,'dbc_by_channel'),'DBC通道映射必须为对象')
|
|
40
|
+
source['dbc_by_channel']={key:str(absolute_path(value,base,field_path_text((*path,'dbc_by_channel',key))))
|
|
41
|
+
for key,value in values.items()}
|
|
42
|
+
except PlanValidationError as error:
|
|
43
|
+
raise locate_error(error,document)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _append_definitions(data, prefix, document, source_prefix, merged, locations, origins, names):
|
|
47
|
+
"""追加一个文件的定义并迁移字段位置。参数: 原定义/目标前缀/原文档/原前缀及本次容器。返回: None。异常: 定义/重复错误。
|
|
48
|
+
|
|
49
|
+
names保存首个同名声明的位置;所有修改仅发生在本次展开容器,无全局状态。
|
|
50
|
+
"""
|
|
51
|
+
for section in SECTIONS:
|
|
52
|
+
if section not in data:continue
|
|
53
|
+
values=data[section]
|
|
54
|
+
expected=dict if section=='derived' else list
|
|
55
|
+
if type(values) is not expected:
|
|
56
|
+
_reject(document,(*source_prefix,section),
|
|
57
|
+
'derived必须为名称到表达式的对象' if section=='derived' else '来源/信号定义必须为数组')
|
|
58
|
+
offset=len(merged[section])
|
|
59
|
+
entries=values.items() if section=='derived' else enumerate(values)
|
|
60
|
+
for index,value in entries:
|
|
61
|
+
path=(*source_prefix,section,index)
|
|
62
|
+
if section!='derived' and type(value) is not dict:
|
|
63
|
+
_reject(document,path,'每项公共定义必须为对象')
|
|
64
|
+
if section=='signals' and 'signals' in value:
|
|
65
|
+
children=value['signals']
|
|
66
|
+
if type(children) is not list or any(type(child) is not dict for child in children):
|
|
67
|
+
_reject(document,(*path,'signals'),'组内signals必须为信号对象数组')
|
|
68
|
+
declarations=[(child.get('name'),(*path,'signals',child_index,'name'))
|
|
69
|
+
for child_index,child in enumerate(children)]
|
|
70
|
+
else:
|
|
71
|
+
name=index if section=='derived' else value.get('name')
|
|
72
|
+
declarations=[(name,path if section=='derived' else (*path,'name'))]
|
|
73
|
+
for name,name_path in declarations:
|
|
74
|
+
if type(name) is not str or not name:
|
|
75
|
+
_reject(document,name_path,'每项公共定义必须明确填写非空名称')
|
|
76
|
+
# 集中声明和普通信号仍共用一个名字空间,组本身没有额外名称。
|
|
77
|
+
identity=('sources' if section=='sources' else 'signals/derived',name)
|
|
78
|
+
if identity in names:
|
|
79
|
+
first_source,first_path=names[identity]
|
|
80
|
+
_reject(document,name_path,'重复定义 '+name,'duplicate_definition',
|
|
81
|
+
'删除或改名;首次声明在 '+first_source+' '+field_path_text(first_path))
|
|
82
|
+
names[identity]=(document.source,name_path)
|
|
83
|
+
copied=deepcopy(value)
|
|
84
|
+
if section=='sources':_source_paths(copied,Path(document.source).parent,path,document)
|
|
85
|
+
if section=='derived':merged[section][name]=copied
|
|
86
|
+
else:merged[section].append(copied)
|
|
87
|
+
# 整个数组只遍历一次位置表,主文件项追加后仍指向主文件原索引。
|
|
88
|
+
original_prefix=(*source_prefix,section)
|
|
89
|
+
for original,location in document.locations.items():
|
|
90
|
+
if original[:len(original_prefix)]!=original_prefix:continue
|
|
91
|
+
suffix=original[len(original_prefix):]
|
|
92
|
+
if not suffix:continue
|
|
93
|
+
target=(*prefix,section,suffix[0] if section=='derived' else offset+suffix[0],*suffix[1:])
|
|
94
|
+
locations[target]=location
|
|
95
|
+
origins[target]=ConfigurationOrigin(document.source,original,location)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def expand_document_imports(document):
|
|
99
|
+
"""展开分析配置或映射中analysis的公共定义。参数: 已解析文档。返回: 可直接静态检查的文档。异常: 配置/读取错误。
|
|
100
|
+
|
|
101
|
+
未声明imports时原样返回,不增加复制或文件读取。批量文件通过每个子计划
|
|
102
|
+
自行使用imports;纯字典API不调用此函数。版本错误由原入口拒绝,不读其导入。
|
|
103
|
+
"""
|
|
104
|
+
data=document.data
|
|
105
|
+
if type(data) is not dict:return document
|
|
106
|
+
prefix=('analysis',) if 'mapping_version' in data else ()
|
|
107
|
+
analysis=data.get('analysis') if prefix else data
|
|
108
|
+
if type(analysis) is not dict or 'imports' not in analysis:return document
|
|
109
|
+
if type(analysis.get('config_version')) is not int or analysis['config_version']!=3:return document
|
|
110
|
+
entries=analysis['imports']
|
|
111
|
+
if type(entries) is not list:
|
|
112
|
+
_reject(document,(*prefix,'imports'),'imports必须为本地配置路径数组')
|
|
113
|
+
# 定义数组重新构造;先清除被移动数组的旧位置,避免缺失字段误用旧索引行列。
|
|
114
|
+
raw=deepcopy(data)
|
|
115
|
+
target=raw['analysis'] if prefix else raw
|
|
116
|
+
merged={'sources':[],'signals':[],'derived':{}}
|
|
117
|
+
locations={path:location for path,location in document.locations.items()
|
|
118
|
+
if not (path[:len(prefix)]==prefix and len(path)>len(prefix)+1
|
|
119
|
+
and path[len(prefix)] in SECTIONS)}
|
|
120
|
+
origins={path:ConfigurationOrigin(document.source,path,location) for path,location in locations.items()}
|
|
121
|
+
names={}
|
|
122
|
+
for index,entry in enumerate(entries):
|
|
123
|
+
path=(*prefix,'imports',index)
|
|
124
|
+
if type(entry) is not str or not entry.strip() or '://' in entry or any(char in entry for char in '*?[]'):
|
|
125
|
+
_reject(document,path,'导入路径必须为明确的本地JSON/YAML文件,不支持URL、通配符或空值')
|
|
126
|
+
imported=load_configuration(Path(document.source).parent/entry)
|
|
127
|
+
fragment=imported.data
|
|
128
|
+
if type(fragment) is not dict or not fragment:
|
|
129
|
+
_reject(imported,(),'公共定义文件必须是非空对象,只能包含sources、signals、derived')
|
|
130
|
+
unknown=set(fragment)-set(SECTIONS)
|
|
131
|
+
if unknown:
|
|
132
|
+
key=next(key for key in fragment if key in unknown)
|
|
133
|
+
_reject(imported,(key,),'公共定义只允许sources、signals、derived;不支持嵌套imports或版本包装')
|
|
134
|
+
_append_definitions(fragment,prefix,imported,(),merged,locations,origins,names)
|
|
135
|
+
_append_definitions(analysis,prefix,document,prefix,merged,locations,origins,names)
|
|
136
|
+
# 展开后不保留imports,执行计划只见一份普通配置;来源位置只在加载期使用。
|
|
137
|
+
target.pop('imports')
|
|
138
|
+
for section in SECTIONS:
|
|
139
|
+
if section!='derived' or merged[section] or section in target:
|
|
140
|
+
target[section]=merged[section]
|
|
141
|
+
from .overrides import apply_overrides
|
|
142
|
+
apply_overrides(target,document,prefix,locations,origins)
|
|
143
|
+
return ConfigurationDocument(raw,document.source,document.format,
|
|
144
|
+
MappingProxyType(locations),MappingProxyType(origins))
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""把已校验的随包合成场景写入新目录,不改写已有文件。"""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from .template_catalog import available_templates, template_files
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def initialize_configuration(scene, output, *, style='annotated'):
|
|
8
|
+
"""生成独立场景。参数: 场景名、新目录及风格。返回: 入口绝对路径。异常: ValueError/IO/取消。
|
|
9
|
+
|
|
10
|
+
先读取全部包资源再独占创建目录,入口最后写出。写入失败仅删除本次创建的文件和目录;
|
|
11
|
+
清理失败附注原错误并保留残余,不删除其他进程写入的文件,不以成功掩盖部分写入。
|
|
12
|
+
"""
|
|
13
|
+
contents=template_files(scene,style=style)
|
|
14
|
+
template=next(t for t in available_templates() if t.name==scene)
|
|
15
|
+
target=Path(output).absolute()
|
|
16
|
+
# mkdir的独占失败发生在清理区之前,已有目录(包括空目录、链接)不属于本次操作。
|
|
17
|
+
target.mkdir()
|
|
18
|
+
created_files=[];created_directories=[target]
|
|
19
|
+
try:
|
|
20
|
+
# 将主入口放在最后,使中途产物不能被误认为完整场景。
|
|
21
|
+
for relative,content in sorted(contents,key=lambda item:item[0]==template.entrypoint):
|
|
22
|
+
path=target/relative
|
|
23
|
+
missing=[];parent=path.parent
|
|
24
|
+
while parent!=target and not parent.exists():missing.append(parent);parent=parent.parent
|
|
25
|
+
for directory in reversed(missing):directory.mkdir();created_directories.append(directory)
|
|
26
|
+
with path.open('xb') as stream:
|
|
27
|
+
created_files.append(path);stream.write(content)
|
|
28
|
+
return target/template.entrypoint
|
|
29
|
+
except BaseException as error:
|
|
30
|
+
for path in reversed(created_files):
|
|
31
|
+
try:path.unlink()
|
|
32
|
+
except OSError as cleanup:error.add_note('未能清理本次文件 '+str(path)+': '+str(cleanup))
|
|
33
|
+
for directory in reversed(created_directories):
|
|
34
|
+
try:directory.rmdir()
|
|
35
|
+
except OSError as cleanup:error.add_note('未能清理本次空目录 '+str(directory)+': '+str(cleanup))
|
|
36
|
+
raise
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""标准库负责JSON语法和数值;轻量第二遍只定位字段,不再构造第二份配置树。"""
|
|
2
|
+
from bisect import bisect_right
|
|
3
|
+
import json
|
|
4
|
+
from math import isfinite
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
from .models import ConfigurationError, ConfigurationLocation
|
|
8
|
+
|
|
9
|
+
MAX_DEPTH=64
|
|
10
|
+
_SPACE=re.compile(r'[ \t\r\n]*')
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _DuplicateKey(ValueError):
|
|
14
|
+
"""只用于让标准库停止覆盖重复键;随后位置扫描给出具体字段。"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _unique_pairs(pairs):
|
|
18
|
+
"""建立唯一键对象。参数: 标准库键值对。返回: dict。异常: 重复键。"""
|
|
19
|
+
result={}
|
|
20
|
+
for key,value in pairs:
|
|
21
|
+
if key in result:
|
|
22
|
+
raise _DuplicateKey(key)
|
|
23
|
+
result[key]=value
|
|
24
|
+
return result
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class _Locations:
|
|
28
|
+
"""只记录JSON路径和偏移,不保留第二份值树;语法真值仍由json.loads决定。"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, text, source):
|
|
31
|
+
"""建立本次扫描状态。参数: 文本/显示来源。返回: owner。异常: 分配失败。"""
|
|
32
|
+
self.text,self.source=text,source
|
|
33
|
+
self.positions={}
|
|
34
|
+
self.lines=[match.start() for match in re.finditer('\n',text)]
|
|
35
|
+
self.decoder=json.JSONDecoder()
|
|
36
|
+
|
|
37
|
+
def location(self, offset):
|
|
38
|
+
"""把字符偏移转换为1基行列。参数: 偏移。返回: 位置。异常: 无。"""
|
|
39
|
+
line=bisect_right(self.lines,offset-1)
|
|
40
|
+
previous=self.lines[line-1] if line else -1
|
|
41
|
+
return ConfigurationLocation(line+1,offset-previous)
|
|
42
|
+
|
|
43
|
+
def scan(self, offset=0, path=(), depth=0):
|
|
44
|
+
"""遍历合法JSON或已知含重复键的JSON。返回: 结束偏移。异常: 重复键/过深/语法错误。"""
|
|
45
|
+
offset=_SPACE.match(self.text,offset).end()
|
|
46
|
+
location=self.location(offset)
|
|
47
|
+
if depth>MAX_DEPTH:
|
|
48
|
+
raise ConfigurationError(self.source,path,location,'nesting_limit','配置嵌套不能超过64层')
|
|
49
|
+
self.positions[path]=location
|
|
50
|
+
first=self.text[offset]
|
|
51
|
+
if first=='{':
|
|
52
|
+
offset=_SPACE.match(self.text,offset+1).end()
|
|
53
|
+
if self.text[offset]=='}':return offset+1
|
|
54
|
+
seen=set()
|
|
55
|
+
while True:
|
|
56
|
+
key_at=offset
|
|
57
|
+
key,offset=json.decoder.scanstring(self.text,offset+1,True)
|
|
58
|
+
if key in seen:
|
|
59
|
+
raise ConfigurationError(self.source,(*path,key),self.location(key_at),
|
|
60
|
+
'duplicate_key',f'重复键:{key}')
|
|
61
|
+
seen.add(key)
|
|
62
|
+
offset=_SPACE.match(self.text,offset).end()+1 # 已通过JSON语法检查的冒号。
|
|
63
|
+
offset=self.scan(offset,(*path,key),depth+1)
|
|
64
|
+
offset=_SPACE.match(self.text,offset).end()
|
|
65
|
+
if self.text[offset]=='}':return offset+1
|
|
66
|
+
offset=_SPACE.match(self.text,offset+1).end()
|
|
67
|
+
if first=='[':
|
|
68
|
+
offset=_SPACE.match(self.text,offset+1).end()
|
|
69
|
+
if self.text[offset]==']':return offset+1
|
|
70
|
+
index=0
|
|
71
|
+
while True:
|
|
72
|
+
offset=self.scan(offset,(*path,index),depth+1)
|
|
73
|
+
offset=_SPACE.match(self.text,offset).end()
|
|
74
|
+
if self.text[offset]==']':return offset+1
|
|
75
|
+
offset=_SPACE.match(self.text,offset+1).end()
|
|
76
|
+
index+=1
|
|
77
|
+
# raw_decode这里只接原子值,绝不重新解码整个容器。
|
|
78
|
+
_,end=self.decoder.raw_decode(self.text,offset)
|
|
79
|
+
return end
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _finite_values(value, source, locations, path=()):
|
|
83
|
+
"""拒绝JSON宽松接受的NaN/Infinity及指数溢出。返回: None。异常: 定位到实际值。"""
|
|
84
|
+
if type(value) is float and not isfinite(value):
|
|
85
|
+
raise ConfigurationError(source,path,locations[path],'nonfinite_number','数值必须有限,不能使用NaN或Infinity')
|
|
86
|
+
if type(value) is dict:
|
|
87
|
+
for key,item in value.items():_finite_values(item,source,locations,(*path,key))
|
|
88
|
+
elif type(value) is list:
|
|
89
|
+
for index,item in enumerate(value):_finite_values(item,source,locations,(*path,index))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def parse_json(text, source):
|
|
93
|
+
"""按标准JSON加载并附准确位置。参数: 文本/来源。返回: 数据和位置表。异常: ConfigurationError。"""
|
|
94
|
+
try:
|
|
95
|
+
try:
|
|
96
|
+
data=json.loads(text,object_pairs_hook=_unique_pairs)
|
|
97
|
+
except _DuplicateKey:
|
|
98
|
+
# 标准库已找到实际重复;不从字符串搜索猜测它属于哪个嵌套对象。
|
|
99
|
+
_Locations(text,source).scan()
|
|
100
|
+
raise AssertionError('JSON重复键位置扫描没有发现重复')
|
|
101
|
+
except json.JSONDecodeError:
|
|
102
|
+
raise
|
|
103
|
+
except (ValueError,OverflowError) as error:
|
|
104
|
+
# Python的十进制整数安全长度限制等数值错误不能泄露为无文件定位的底层异常。
|
|
105
|
+
raise ConfigurationError(source,(),None,'invalid_number','数字超出当前Python可解析的范围') from error
|
|
106
|
+
scanner=_Locations(text,source)
|
|
107
|
+
scanner.scan()
|
|
108
|
+
_finite_values(data,source,scanner.positions)
|
|
109
|
+
return data,scanner.positions
|
|
110
|
+
except json.JSONDecodeError as error:
|
|
111
|
+
raise ConfigurationError(source,(),ConfigurationLocation(error.lineno,error.colno),
|
|
112
|
+
'invalid_json',error.msg) from error
|
|
113
|
+
except RecursionError as error:
|
|
114
|
+
raise ConfigurationError(source,(),None,'nesting_limit','配置嵌套不能超过64层') from error
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""配置加载期的原生数据、字段位置和语法错误,不参与分析执行或来源读取。"""
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def field_path_text(path):
|
|
8
|
+
"""把键/数组下标路径变成无歧义文本。参数: tuple。返回: JSON路径。异常: 非内部路径。"""
|
|
9
|
+
result='$'
|
|
10
|
+
for part in path:
|
|
11
|
+
if type(part) is int:
|
|
12
|
+
result+=f'[{part}]'
|
|
13
|
+
elif type(part) is str:
|
|
14
|
+
result+=('.'+part if part.isidentifier() else '['+json.dumps(part,ensure_ascii=False)+']')
|
|
15
|
+
else:
|
|
16
|
+
raise TypeError('配置字段路径只接受文本键或整数下标')
|
|
17
|
+
return result
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True, slots=True)
|
|
21
|
+
class ConfigurationLocation:
|
|
22
|
+
"""一处源码位置;行列从1开始,列按Unicode字符计,不按UTF-8字节计。"""
|
|
23
|
+
line: int
|
|
24
|
+
column: int
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class ConfigurationOrigin:
|
|
29
|
+
"""展开字段的声明位置;只保存文件名、字段路径及行列,不保存第二份配置。"""
|
|
30
|
+
source: str # 实际声明文件的词法绝对路径。
|
|
31
|
+
field_path: tuple # 声明文件内部路径,索引尚未被合并重排。
|
|
32
|
+
location: ConfigurationLocation | None # 原文一基行列;无法取得时为None。
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True, slots=True)
|
|
36
|
+
class ConfigurationDocument:
|
|
37
|
+
"""只在加载期间持有原生值和必要位置;调用者构造计划后释放本对象。"""
|
|
38
|
+
data: object
|
|
39
|
+
source: str
|
|
40
|
+
format: str
|
|
41
|
+
locations: Mapping
|
|
42
|
+
origins: Mapping = field(default_factory=dict) # 仅文件导入展开时填充,计划构造后释放。
|
|
43
|
+
|
|
44
|
+
def origin_for(self, field_path):
|
|
45
|
+
"""查最近声明来源并保留缺失字段后缀。参数: tuple路径。返回: 来源或None。异常: 无。"""
|
|
46
|
+
original=tuple(field_path)
|
|
47
|
+
path=original
|
|
48
|
+
# 缺少字段只能沿所属对象定位,不能捏造它在原文件中的行列。
|
|
49
|
+
while path not in self.origins and path:
|
|
50
|
+
path=path[:-1]
|
|
51
|
+
origin=self.origins.get(path)
|
|
52
|
+
if origin is None:return None
|
|
53
|
+
return ConfigurationOrigin(origin.source,origin.field_path+original[len(path):],origin.location)
|
|
54
|
+
|
|
55
|
+
def location_for(self, field_path):
|
|
56
|
+
"""取具体值位置,缺少字段时回溯最近父对象。参数: tuple路径。返回: 位置或None。异常: 无。"""
|
|
57
|
+
path=tuple(field_path)
|
|
58
|
+
while path not in self.locations and path:
|
|
59
|
+
path=path[:-1]
|
|
60
|
+
return self.locations.get(path)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class ConfigurationError(ValueError):
|
|
64
|
+
"""保存语法错误码、文件和字段位置;消息不打印整份配置或执行任意内容。"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, source, field_path, location, code, message):
|
|
67
|
+
"""建立错误事实。参数: 来源/tuple路径/位置/代码/原因。返回: None。异常: 无。"""
|
|
68
|
+
self.source=source
|
|
69
|
+
self.field_path=tuple(field_path)
|
|
70
|
+
self.location=location
|
|
71
|
+
self.code=code
|
|
72
|
+
self.message=message
|
|
73
|
+
place=source if location is None else f'{source}:{location.line}:{location.column}'
|
|
74
|
+
super().__init__(f'{place} {field_path_text(self.field_path)}: {message}')
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""按请求说明定义或叶字段来自哪个配置文件;不作为执行计划的持久状态。
|
|
2
|
+
|
|
3
|
+
只读主配置与明确的一层公共定义,先复用静态校验再生成小型来源记录。
|
|
4
|
+
默认报告定义位置及来源文件路径;fields模式列全部显式叶字段,不虚构默认值来源。
|
|
5
|
+
既不读取CSV/DBC等业务输入,也不写报告文件;调用者决定显示或重定向。
|
|
6
|
+
"""
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from . import load_configuration
|
|
10
|
+
from .imports import expand_document_imports
|
|
11
|
+
from .file_tools import validate_document
|
|
12
|
+
from .models import field_path_text
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _at(data, path):
|
|
16
|
+
"""读取存在的字段,跳过展开后已删除的imports位置。参数: 原生树/tuple路径。返回: (存在,值)。异常: 无。"""
|
|
17
|
+
current=data
|
|
18
|
+
for key in path:
|
|
19
|
+
if type(current) is dict and key in current:current=current[key]
|
|
20
|
+
elif type(current) is list and type(key) is int and 0<=key<len(current):current=current[key]
|
|
21
|
+
else:return False,None
|
|
22
|
+
return True,current
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _record(document, path, name=None):
|
|
26
|
+
"""复制一项有限来源事实。参数: 文档、路径、可选定义名。返回: dict。异常: 无。"""
|
|
27
|
+
origin=document.origin_for(path)
|
|
28
|
+
location=origin.location if origin else document.location_for(path)
|
|
29
|
+
return dict(name=name,effective_path=field_path_text(path),
|
|
30
|
+
declared_path=field_path_text(origin.field_path if origin else path),
|
|
31
|
+
file=origin.source if origin else document.source,
|
|
32
|
+
line=None if location is None else location.line,
|
|
33
|
+
column=None if location is None else location.column)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def configuration_origins(source, *, fields=False):
|
|
37
|
+
"""读取实际定义或叶字段的声明位置。参数: 配置路径、是否逐字段。返回: 来源报告dict。异常: 配置/读取错误。
|
|
38
|
+
|
|
39
|
+
分析和映射都列其定义;批量只列本文件的任务,不读取子计划。省略的默认字段
|
|
40
|
+
不在报告内。fields只保位置而不复制值;路径声明单独说明最终指向。
|
|
41
|
+
"""
|
|
42
|
+
path=Path(source).absolute()
|
|
43
|
+
document=expand_document_imports(load_configuration(path))
|
|
44
|
+
kind=validate_document(document,path.parent)
|
|
45
|
+
items=[]
|
|
46
|
+
if fields:
|
|
47
|
+
for parts in document.locations:
|
|
48
|
+
exists,value=_at(document.data,parts)
|
|
49
|
+
if exists and type(value) not in (dict,list):items.append(_record(document,parts))
|
|
50
|
+
else:
|
|
51
|
+
prefix=('analysis',) if kind=='mapping' else ()
|
|
52
|
+
analysis=document.data['analysis'] if prefix else document.data
|
|
53
|
+
if kind=='batch' and 'template' in analysis:
|
|
54
|
+
item=_record(document,('template',),'template')
|
|
55
|
+
item['resolved_paths']=[str((path.parent/analysis['template']).absolute())]
|
|
56
|
+
items.append(item)
|
|
57
|
+
items.append(_record(document,('inputs',),'inputs'))
|
|
58
|
+
sections=('jobs',) if kind=='batch' else ('sources','signals','derived')
|
|
59
|
+
for section in sections:
|
|
60
|
+
values=analysis.get(section,{} if section=='derived' else [])
|
|
61
|
+
entries=values.items() if section=='derived' else enumerate(values)
|
|
62
|
+
for key,value in entries:
|
|
63
|
+
if section=='signals' and 'signals' in value:
|
|
64
|
+
for child_index,child in enumerate(value['signals']):
|
|
65
|
+
items.append(_record(document,(*prefix,section,key,'signals',child_index),child['name']))
|
|
66
|
+
continue
|
|
67
|
+
name=key if section=='derived' else value.get('name')
|
|
68
|
+
item=_record(document,(*prefix,section,key),name)
|
|
69
|
+
# 文件位置只按已知路径字段说明;metadata内路径文字不解释。
|
|
70
|
+
if section=='sources':
|
|
71
|
+
from ..planning.input_paths import source_path_fields
|
|
72
|
+
declared=[owner[key] for owner,key in source_path_fields(value)]
|
|
73
|
+
declared.extend(value.get('dbc_by_channel',{}).values())
|
|
74
|
+
item['resolved_paths']=[str((path.parent/entry).absolute()) for entry in declared]
|
|
75
|
+
elif section=='jobs':item['resolved_paths']=[str((path.parent/value['plan']).absolute())]
|
|
76
|
+
items.append(item)
|
|
77
|
+
return dict(configuration=str(path),configuration_type=kind,
|
|
78
|
+
scope='fields' if fields else 'definitions',items=items)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def render_origins(report):
|
|
82
|
+
"""将有限来源记录显示为中文文本。参数: configuration_origins报告。返回: str。异常: 内部报告结构错误。"""
|
|
83
|
+
lines=['配置来源:'+report['configuration'],
|
|
84
|
+
'只列显式声明;未读取业务输入。批量任务的子配置需单独查看。']
|
|
85
|
+
for item in report['items']:
|
|
86
|
+
place=item['file']
|
|
87
|
+
if item['line'] is not None:place+=f":{item['line']}:{item['column']}"
|
|
88
|
+
lines.append(item['effective_path']+' ← '+place+' '+item['declared_path'])
|
|
89
|
+
for path in item.get('resolved_paths',[]):lines.append(' 文件路径:'+path)
|
|
90
|
+
return '\n'.join(lines)+'\n'
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""只覆盖公共定义中的明确配置项,不允许隐藏改名、添加对象或递归合并自由数据。
|
|
2
|
+
|
|
3
|
+
覆盖值按主文件定位,随后仍由普通计划校验器检查;来源表同时指回真正的覆盖位置。
|
|
4
|
+
"""
|
|
5
|
+
from copy import deepcopy
|
|
6
|
+
from .models import ConfigurationOrigin
|
|
7
|
+
|
|
8
|
+
ALLOWED={
|
|
9
|
+
'sources':{'path','paths','dbc_by_channel','time','reader'},
|
|
10
|
+
'signals':{'dtype','unit','valid_for','period','conversion','choices','valid_range','invalid_values','sample_policy','same_time_policy'},
|
|
11
|
+
'derived':{'expr','unit'},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def apply_overrides(target, document, prefix, locations, origins):
|
|
16
|
+
"""修改本次独立副本;参数含原文位置。返回None;非法对象/字段经_imports._reject定位。"""
|
|
17
|
+
from .imports import _reject, _source_paths
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
raw=target.pop('overrides',{})
|
|
20
|
+
if type(raw) is not dict or set(raw)-set(ALLOWED):
|
|
21
|
+
_reject(document,(*prefix,'overrides'),'overrides仅允许sources/signals/derived对象')
|
|
22
|
+
for section,items in raw.items():
|
|
23
|
+
where=(*prefix,'overrides',section)
|
|
24
|
+
if type(items) is not dict:_reject(document,where,'覆盖项须按已有名称索引')
|
|
25
|
+
catalog={}
|
|
26
|
+
if section=='derived':
|
|
27
|
+
catalog={name:(value,(*prefix,section,name)) for name,value in target.get(section,{}).items()}
|
|
28
|
+
else:
|
|
29
|
+
for index,value in enumerate(target.get(section,[])):
|
|
30
|
+
if section=='signals' and 'signals' in value:
|
|
31
|
+
for ci,child in enumerate(value['signals']):catalog[child['name']]=(child,(*prefix,section,index,'signals',ci))
|
|
32
|
+
else:catalog[value['name']]=(value,(*prefix,section,index))
|
|
33
|
+
for name,changes in items.items():
|
|
34
|
+
path=(*where,name)
|
|
35
|
+
if name not in catalog:_reject(document,path,'覆盖目标不存在,不允许新增定义')
|
|
36
|
+
if type(changes) is not dict or not changes or set(changes)-ALLOWED[section]:
|
|
37
|
+
_reject(document,path,'覆盖字段不在允许列表;不能改名、改绑定或修改自由metadata')
|
|
38
|
+
value,target_path=catalog[name]
|
|
39
|
+
# path/paths是同一输入声明的两种形状,只保留用户本次选定的一种。
|
|
40
|
+
if section=='sources':
|
|
41
|
+
if 'path' in changes and 'paths' not in changes:value.pop('paths',None)
|
|
42
|
+
if 'paths' in changes and 'path' not in changes:value.pop('path',None)
|
|
43
|
+
# 被整体替换的字段不再保留旧叶子来源,例如旧time.clock已被省略。
|
|
44
|
+
replaced=set(changes)
|
|
45
|
+
if section=='sources' and replaced & {'path','paths'}:replaced.update(('path','paths'))
|
|
46
|
+
for effective in tuple(origins):
|
|
47
|
+
if effective[:len(target_path)]==target_path and len(effective)>len(target_path) and effective[len(target_path)] in replaced:
|
|
48
|
+
origins.pop(effective,None);locations.pop(effective,None)
|
|
49
|
+
value.update(deepcopy(changes))
|
|
50
|
+
if section=='sources':_source_paths(value,Path(document.source).parent,path,document)
|
|
51
|
+
for original,location in document.locations.items():
|
|
52
|
+
if original[:len(path)]==path and len(original)>len(path):
|
|
53
|
+
effective=(*target_path,*original[len(path):])
|
|
54
|
+
locations[effective]=location
|
|
55
|
+
origins[effective]=ConfigurationOrigin(document.source,original,location)
|