mainsequence 7.0.0__tar.gz → 7.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. {mainsequence-7.0.0/mainsequence.egg-info → mainsequence-7.0.1}/PKG-INFO +1 -1
  2. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/metatables/core.py +47 -3
  3. {mainsequence-7.0.0 → mainsequence-7.0.1/mainsequence.egg-info}/PKG-INFO +1 -1
  4. {mainsequence-7.0.0 → mainsequence-7.0.1}/pyproject.toml +1 -1
  5. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_scheduler_client_model.py +53 -3
  6. {mainsequence-7.0.0 → mainsequence-7.0.1}/LICENSE +0 -0
  7. {mainsequence-7.0.0 → mainsequence-7.0.1}/MANIFEST.in +0 -0
  8. {mainsequence-7.0.0 → mainsequence-7.0.1}/README.md +0 -0
  9. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/AGENTS.md +0 -0
  10. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  11. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  12. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  13. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  14. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  15. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
  16. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  17. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
  18. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  19. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  20. {mainsequence-7.0.0 → mainsequence-7.0.1}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
  21. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/__init__.py +0 -0
  22. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/__main__.py +0 -0
  23. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/bootstrap.py +0 -0
  24. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/__init__.py +0 -0
  25. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/api.py +0 -0
  26. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/browser_auth.py +0 -0
  27. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/cli.py +0 -0
  28. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/config.py +0 -0
  29. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/docker_utils.py +0 -0
  30. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/doctor.py +0 -0
  31. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/local_ops.py +0 -0
  32. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/migrations.py +0 -0
  33. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/model_filters.py +0 -0
  34. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/project_status.py +0 -0
  35. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/pydantic_cli.py +0 -0
  36. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/sdk_utils.py +0 -0
  37. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/ssh_utils.py +0 -0
  38. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/cli/ui.py +0 -0
  39. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/__init__.py +0 -0
  40. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/agent_runtime_models.py +0 -0
  41. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/base.py +0 -0
  42. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/client.py +0 -0
  43. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/compute_validation.py +0 -0
  44. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  45. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  46. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  47. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  48. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/dtype_codec.py +0 -0
  49. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/exceptions.py +0 -0
  50. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/metatables/__init__.py +0 -0
  51. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/models_foundry.py +0 -0
  52. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/models_helpers.py +0 -0
  53. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/models_user.py +0 -0
  54. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/observability.py +0 -0
  55. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/client/utils.py +0 -0
  56. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/defaults.py +0 -0
  57. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/instrumentation/__init__.py +0 -0
  58. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/instrumentation/utils.py +0 -0
  59. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/logconf.py +0 -0
  60. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/__init__.py +0 -0
  61. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/__main__.py +0 -0
  62. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  63. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  64. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/future_registry.py +0 -0
  65. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/hashing.py +0 -0
  66. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  67. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  68. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/env.py +0 -0
  69. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/provider.py +0 -0
  70. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/registry.py +0 -0
  71. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  72. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  73. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  74. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  75. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  76. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/schema_names.py +0 -0
  77. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  78. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
  79. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
  80. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
  81. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
  82. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
  83. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
  84. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
  85. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
  86. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
  87. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/project_context.py +0 -0
  88. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/project_skills.py +0 -0
  89. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/runtime_flags.py +0 -0
  90. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence/scaffold_skills.py +0 -0
  91. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence.egg-info/SOURCES.txt +0 -0
  92. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence.egg-info/dependency_links.txt +0 -0
  93. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence.egg-info/entry_points.txt +0 -0
  94. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence.egg-info/requires.txt +0 -0
  95. {mainsequence-7.0.0 → mainsequence-7.0.1}/mainsequence.egg-info/top_level.txt +0 -0
  96. {mainsequence-7.0.0 → mainsequence-7.0.1}/setup.cfg +0 -0
  97. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
  98. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_auth_precedence.py +0 -0
  99. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_canonical_api_route_contract.py +0 -0
  100. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_cli.py +0 -0
  101. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_cli_browser_auth.py +0 -0
  102. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_cli_migrations.py +0 -0
  103. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_client.py +0 -0
  104. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_dependency_extras.py +0 -0
  105. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_duckdb_interface_dimensions.py +0 -0
  106. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_environment_resource_context.py +0 -0
  107. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_environment_response_contracts.py +0 -0
  108. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_filter_normalization.py +0 -0
  109. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_instrumentation.py +0 -0
  110. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_local_ops.py +0 -0
  111. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_logconf.py +0 -0
  112. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_meta_table_migrations.py +0 -0
  113. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_meta_tables_client_models.py +0 -0
  114. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  115. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_models_user_request_bound_auth.py +0 -0
  116. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_notification_uid_contract.py +0 -0
  117. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_observability_client.py +0 -0
  118. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_pod_project_resolution.py +0 -0
  119. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_project_batch_jobs_from_file.py +0 -0
  120. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_project_branch_contract.py +0 -0
  121. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_project_runtime_context.py +0 -0
  122. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_project_skills.py +0 -0
  123. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_scaffold_skills.py +0 -0
  124. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_schema_names.py +0 -0
  125. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_secret_client_model.py +0 -0
  126. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_source_table_configuration.py +0 -0
  127. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_sqlite_interface_dimensions.py +0 -0
  128. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_ssh_utils.py +0 -0
  129. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_access_dimension_audit.py +0 -0
  130. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_dimension_queries.py +0 -0
  131. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_update_configuration.py +0 -0
  132. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_update_configuration_client.py +0 -0
  133. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_update_flow.py +0 -0
  134. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_time_index_table_update_hard_cut.py +0 -0
  135. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_update_runner_uid_runtime.py +0 -0
  136. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_update_statistics.py +0 -0
  137. {mainsequence-7.0.0 → mainsequence-7.0.1}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 7.0.0
3
+ Version: 7.0.1
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -3843,6 +3843,49 @@ class TimeIndexMetaTable(MetaTable):
3843
3843
  )
3844
3844
 
3845
3845
 
3846
+ class ScheduledUpdateNode(BasePydanticModel):
3847
+ """Strict read projection for an update node attached to a Scheduler.
3848
+
3849
+ Scheduler endpoints return a flattened polymorphic node projection with
3850
+ output-table identity. This is intentionally separate from
3851
+ :class:`TableUpdateNode`, which models the full update graph resource.
3852
+ """
3853
+
3854
+ model_config = ConfigDict(extra="forbid")
3855
+
3856
+ uid: str = Field(..., description="Public uid of the scheduled update node")
3857
+ node_type: str = Field(..., min_length=1, description="Scheduled-node discriminator")
3858
+ update_hash: str | None = Field(
3859
+ ...,
3860
+ max_length=63,
3861
+ description="Update identity when exposed by the concrete scheduled node",
3862
+ )
3863
+ build_configuration: dict[str, Any] | None = Field(
3864
+ ...,
3865
+ description="Serialized build configuration exposed by the concrete node",
3866
+ )
3867
+ output_table_uid: str | None = Field(
3868
+ ...,
3869
+ description="Canonical public uid of the scheduled node's output table",
3870
+ )
3871
+ output_table_type: str | None = Field(
3872
+ ...,
3873
+ description="Output-table discriminator exposed by the backend",
3874
+ )
3875
+ output_table_physical_table_name: str | None = Field(
3876
+ ...,
3877
+ description="Physical table name of the scheduled node's output",
3878
+ )
3879
+ output_table_identifier: str | None = Field(
3880
+ ...,
3881
+ description="Published identifier of the scheduled node's output table",
3882
+ )
3883
+ output_table_data_source_uid: str | None = Field(
3884
+ ...,
3885
+ description="Canonical data-source uid of the scheduled node's output table",
3886
+ )
3887
+
3888
+
3846
3889
  class Scheduler(BasePydanticModel, BaseObjectOrm):
3847
3890
  uid: str | None = Field(None, description="Public uid of this scheduler")
3848
3891
  organization_environment_uid: str = Field(
@@ -3861,9 +3904,9 @@ class Scheduler(BasePydanticModel, BaseObjectOrm):
3861
3904
  api_address: str | None
3862
3905
  api_port: int | None
3863
3906
  last_heart_beat: datetime.datetime | None = None
3864
- pre_loads_in_tree: list[TableUpdateNode] | None = None
3865
- in_active_tree: list[TableUpdateNode] | None = None
3866
- schedules_to: list[TableUpdateNode] | None = None
3907
+ pre_loads_in_tree: list[ScheduledUpdateNode] | None = None
3908
+ in_active_tree: list[ScheduledUpdateNode] | None = None
3909
+ schedules_to: list[ScheduledUpdateNode] | None = None
3867
3910
  # for heartbeat
3868
3911
  _stop_heart_beat: bool = False
3869
3912
  _executor: object | None = None
@@ -5121,6 +5164,7 @@ __all__ = [
5121
5164
  "MetaTableValidateContractRequest",
5122
5165
  "PodDataSource",
5123
5166
  "TimeIndexTableUpdateConfiguration",
5167
+ "ScheduledUpdateNode",
5124
5168
  "Scheduler",
5125
5169
  "SchedulerDoesNotExist",
5126
5170
  "SessionDataSource",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 7.0.0
3
+ Version: 7.0.1
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "7.0.0"
7
+ version = "7.0.1"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -6,6 +6,28 @@ import mainsequence.client.metatables.core as core_mod
6
6
  ENVIRONMENT_UID = "58218213-5e4e-43de-a5bd-6757f4e1c8f6"
7
7
  SCHEDULER_UID = "00000000-0000-4000-8000-000000000001"
8
8
  UPDATE_NODE_UID = "00000000-0000-4000-8000-000000000002"
9
+ OUTPUT_TABLE_UID = "00000000-0000-4000-8000-000000000003"
10
+ DATA_SOURCE_UID = "00000000-0000-4000-8000-000000000004"
11
+
12
+
13
+ def _scheduled_node_payload():
14
+ return {
15
+ "uid": UPDATE_NODE_UID,
16
+ "node_type": "time_index_table_update",
17
+ "update_hash": "pricesupdater_0123456789abcdef0123456789abcdef",
18
+ "build_configuration": {
19
+ "configuration_schema_version": 2,
20
+ "table_updater_class_import_path": {
21
+ "module": "tutorial.prices",
22
+ "qualname": "PricesUpdater",
23
+ },
24
+ },
25
+ "output_table_uid": OUTPUT_TABLE_UID,
26
+ "output_table_type": "time_index_meta_table",
27
+ "output_table_physical_table_name": "prices",
28
+ "output_table_identifier": "prices",
29
+ "output_table_data_source_uid": DATA_SOURCE_UID,
30
+ }
9
31
 
10
32
 
11
33
  def _scheduler_payload():
@@ -21,9 +43,9 @@ def _scheduler_payload():
21
43
  "api_address": None,
22
44
  "api_port": None,
23
45
  "last_heart_beat": None,
24
- "pre_loads_in_tree": [],
25
- "in_active_tree": [],
26
- "schedules_to": [],
46
+ "pre_loads_in_tree": [_scheduled_node_payload()],
47
+ "in_active_tree": [_scheduled_node_payload()],
48
+ "schedules_to": [_scheduled_node_payload()],
27
49
  }
28
50
 
29
51
 
@@ -51,6 +73,32 @@ def test_scheduler_strict_model_accepts_environment_projection():
51
73
  )
52
74
 
53
75
 
76
+ def test_scheduler_strict_model_accepts_canonical_scheduled_node_projection():
77
+ scheduler = core_mod.Scheduler.model_validate(_scheduler_payload())
78
+
79
+ for relation_name in ("pre_loads_in_tree", "in_active_tree", "schedules_to"):
80
+ scheduled_nodes = getattr(scheduler, relation_name)
81
+ assert scheduled_nodes is not None
82
+ assert len(scheduled_nodes) == 1
83
+ scheduled_node = scheduled_nodes[0]
84
+ assert isinstance(scheduled_node, core_mod.ScheduledUpdateNode)
85
+ assert scheduled_node.uid == UPDATE_NODE_UID
86
+ assert scheduled_node.node_type == "time_index_table_update"
87
+ assert scheduled_node.output_table_uid == OUTPUT_TABLE_UID
88
+ assert scheduled_node.output_table_type == "time_index_meta_table"
89
+ assert scheduled_node.output_table_physical_table_name == "prices"
90
+ assert scheduled_node.output_table_identifier == "prices"
91
+ assert scheduled_node.output_table_data_source_uid == DATA_SOURCE_UID
92
+
93
+
94
+ def test_scheduler_strict_model_rejects_unknown_scheduled_node_projection():
95
+ payload = _scheduler_payload()
96
+ payload["schedules_to"][0]["unexpected_node_projection"] = "rejected"
97
+
98
+ with pytest.raises(ValidationError, match="unexpected_node_projection"):
99
+ core_mod.Scheduler.model_validate(payload)
100
+
101
+
54
102
  def test_scheduler_build_derives_environment_without_request_override(monkeypatch):
55
103
  captured = {}
56
104
 
@@ -77,6 +125,8 @@ def test_scheduler_build_derives_environment_without_request_override(monkeypatc
77
125
  assert request_body["update_node_uids"] == [UPDATE_NODE_UID]
78
126
  assert captured["time_out"] == 11
79
127
  assert scheduler.organization_environment_uid == ENVIRONMENT_UID
128
+ assert scheduler.schedules_to is not None
129
+ assert scheduler.schedules_to[0].output_table_uid == OUTPUT_TABLE_UID
80
130
 
81
131
 
82
132
  def test_scheduler_get_for_update_node_accepts_environment_projection(monkeypatch):
File without changes
File without changes
File without changes
File without changes