mainsequence 6.0.44__tar.gz → 6.0.45__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 (131) hide show
  1. {mainsequence-6.0.44/mainsequence.egg-info → mainsequence-6.0.45}/PKG-INFO +1 -1
  2. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/metatables/core.py +7 -0
  3. {mainsequence-6.0.44 → mainsequence-6.0.45/mainsequence.egg-info}/PKG-INFO +1 -1
  4. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence.egg-info/SOURCES.txt +2 -0
  5. {mainsequence-6.0.44 → mainsequence-6.0.45}/pyproject.toml +1 -1
  6. mainsequence-6.0.45/tests/test_environment_response_contracts.py +96 -0
  7. mainsequence-6.0.45/tests/test_scheduler_client_model.py +122 -0
  8. {mainsequence-6.0.44 → mainsequence-6.0.45}/LICENSE +0 -0
  9. {mainsequence-6.0.44 → mainsequence-6.0.45}/README.md +0 -0
  10. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/AGENTS.md +0 -0
  11. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +0 -0
  12. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  13. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  14. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  15. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  16. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  17. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  18. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/maintenance/project-maintenance/SKILL.md +0 -0
  19. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  20. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  21. {mainsequence-6.0.44 → mainsequence-6.0.45}/agent_scaffold/skills/sdk_project_execution/SKILL.md +0 -0
  22. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/__init__.py +0 -0
  23. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/__main__.py +0 -0
  24. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/bootstrap.py +0 -0
  25. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/__init__.py +0 -0
  26. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/api.py +0 -0
  27. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/browser_auth.py +0 -0
  28. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/cli.py +0 -0
  29. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/config.py +0 -0
  30. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/docker_utils.py +0 -0
  31. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/doctor.py +0 -0
  32. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/local_ops.py +0 -0
  33. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/migrations.py +0 -0
  34. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/model_filters.py +0 -0
  35. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/project_status.py +0 -0
  36. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/pydantic_cli.py +0 -0
  37. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/sdk_utils.py +0 -0
  38. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/ssh_utils.py +0 -0
  39. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/cli/ui.py +0 -0
  40. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/__init__.py +0 -0
  41. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/agent_runtime_models.py +0 -0
  42. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/base.py +0 -0
  43. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/client.py +0 -0
  44. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/compute_validation.py +0 -0
  45. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  46. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  47. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  48. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  49. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/dtype_codec.py +0 -0
  50. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/exceptions.py +0 -0
  51. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/metatables/__init__.py +0 -0
  52. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/models_foundry.py +0 -0
  53. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/models_helpers.py +0 -0
  54. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/models_user.py +0 -0
  55. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/client/utils.py +0 -0
  56. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/defaults.py +0 -0
  57. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/instrumentation/__init__.py +0 -0
  58. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/instrumentation/utils.py +0 -0
  59. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/logconf.py +0 -0
  60. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/__init__.py +0 -0
  61. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/__main__.py +0 -0
  62. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  63. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  64. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  65. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  66. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
  67. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  68. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  69. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
  70. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  71. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  72. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/future_registry.py +0 -0
  73. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/hashing.py +0 -0
  74. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  75. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  76. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/env.py +0 -0
  77. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/provider.py +0 -0
  78. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/registry.py +0 -0
  79. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  80. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  81. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  82. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  83. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  84. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/schema_names.py +0 -0
  85. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  86. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/project_context.py +0 -0
  87. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/project_skills.py +0 -0
  88. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/runtime_flags.py +0 -0
  89. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence/scaffold_skills.py +0 -0
  90. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence.egg-info/dependency_links.txt +0 -0
  91. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence.egg-info/entry_points.txt +0 -0
  92. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence.egg-info/requires.txt +0 -0
  93. {mainsequence-6.0.44 → mainsequence-6.0.45}/mainsequence.egg-info/top_level.txt +0 -0
  94. {mainsequence-6.0.44 → mainsequence-6.0.45}/setup.cfg +0 -0
  95. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_auth_precedence.py +0 -0
  96. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_build_operations_hashing.py +0 -0
  97. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_canonical_api_route_contract.py +0 -0
  98. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_cli.py +0 -0
  99. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_cli_browser_auth.py +0 -0
  100. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_cli_migrations.py +0 -0
  101. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_client.py +0 -0
  102. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  103. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_data_node_storage_dimension_queries.py +0 -0
  104. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_data_node_update_flow.py +0 -0
  105. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_dependency_extras.py +0 -0
  106. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_duckdb_interface_dimensions.py +0 -0
  107. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_environment_resource_context.py +0 -0
  108. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_filter_normalization.py +0 -0
  109. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_instrumentation.py +0 -0
  110. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_local_ops.py +0 -0
  111. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_logconf.py +0 -0
  112. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_meta_table_migrations.py +0 -0
  113. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_meta_tables_client_models.py +0 -0
  114. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  115. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_models_user_request_bound_auth.py +0 -0
  116. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_notification_uid_contract.py +0 -0
  117. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_pod_project_resolution.py +0 -0
  118. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_project_batch_jobs_from_file.py +0 -0
  119. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_project_branch_contract.py +0 -0
  120. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_project_runtime_context.py +0 -0
  121. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_project_skills.py +0 -0
  122. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_run_configuration.py +0 -0
  123. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_scaffold_skills.py +0 -0
  124. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_schema_names.py +0 -0
  125. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_secret_client_model.py +0 -0
  126. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_source_table_configuration.py +0 -0
  127. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_sqlite_interface_dimensions.py +0 -0
  128. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_ssh_utils.py +0 -0
  129. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_update_runner_uid_runtime.py +0 -0
  130. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_update_statistics.py +0 -0
  131. {mainsequence-6.0.44 → mainsequence-6.0.45}/tests/test_update_uid_guards.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 6.0.44
3
+ Version: 6.0.45
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -3719,6 +3719,13 @@ class TimeIndexMetaTable(MetaTable):
3719
3719
 
3720
3720
  class Scheduler(BasePydanticModel, BaseObjectOrm):
3721
3721
  uid: str | None = Field(None, description="Public uid of this scheduler")
3722
+ organization_project_environment_uid: str = Field(
3723
+ ...,
3724
+ description=(
3725
+ "Read-only public UID of the Organization Environment derived by the "
3726
+ "backend from the scheduler's update nodes."
3727
+ ),
3728
+ )
3722
3729
  name: str
3723
3730
  is_running: bool
3724
3731
  running_process_pid: int | None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 6.0.44
3
+ Version: 6.0.45
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License-Expression: LicenseRef-MainSequence-Proprietary
@@ -101,6 +101,7 @@ tests/test_data_node_update_flow.py
101
101
  tests/test_dependency_extras.py
102
102
  tests/test_duckdb_interface_dimensions.py
103
103
  tests/test_environment_resource_context.py
104
+ tests/test_environment_response_contracts.py
104
105
  tests/test_filter_normalization.py
105
106
  tests/test_instrumentation.py
106
107
  tests/test_local_ops.py
@@ -117,6 +118,7 @@ tests/test_project_runtime_context.py
117
118
  tests/test_project_skills.py
118
119
  tests/test_run_configuration.py
119
120
  tests/test_scaffold_skills.py
121
+ tests/test_scheduler_client_model.py
120
122
  tests/test_schema_names.py
121
123
  tests/test_secret_client_model.py
122
124
  tests/test_source_table_configuration.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "6.0.44"
7
+ version = "6.0.45"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -0,0 +1,96 @@
1
+ import pytest
2
+
3
+ import mainsequence.client.agent_runtime_models as agent_models
4
+ import mainsequence.client.metatables.core as metatable_models
5
+ import mainsequence.client.models_foundry as foundry_models
6
+ import mainsequence.client.models_helpers as helper_models
7
+
8
+ ENVIRONMENT_UID_FIELD = "organization_project_environment_uid"
9
+ ENVIRONMENT_NAME_FIELD = "organization_project_environment_name"
10
+
11
+
12
+ @pytest.mark.parametrize(
13
+ ("serializer_names", "model", "expected_fields"),
14
+ [
15
+ pytest.param(
16
+ ("AgentSerializer",),
17
+ agent_models.Agent,
18
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
19
+ id="agent",
20
+ ),
21
+ pytest.param(
22
+ ("AgentSemanticSearchResultSerializer",),
23
+ agent_models.AgentSemanticSearchResult,
24
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
25
+ id="agent-semantic-search-result",
26
+ ),
27
+ pytest.param(
28
+ ("JobSerializer",),
29
+ helper_models.Job,
30
+ {ENVIRONMENT_UID_FIELD},
31
+ id="job",
32
+ ),
33
+ pytest.param(
34
+ ("JobRunSerializer", "JobRunLightSerializer"),
35
+ helper_models.JobRun,
36
+ {ENVIRONMENT_UID_FIELD},
37
+ id="job-run",
38
+ ),
39
+ pytest.param(
40
+ ("ProjectBranchSerializer",),
41
+ foundry_models.ProjectBranch,
42
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
43
+ id="project-branch",
44
+ ),
45
+ pytest.param(
46
+ ("BucketSerializer",),
47
+ foundry_models.Bucket,
48
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
49
+ id="bucket",
50
+ ),
51
+ pytest.param(
52
+ ("ArtifactSerializer",),
53
+ foundry_models.Artifact,
54
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
55
+ id="artifact",
56
+ ),
57
+ pytest.param(
58
+ ("SecretNameSerializer", "SecretValueSerializer"),
59
+ foundry_models.Secret,
60
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
61
+ id="secret",
62
+ ),
63
+ pytest.param(
64
+ ("ConstantSerializer",),
65
+ foundry_models.Constant,
66
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
67
+ id="constant",
68
+ ),
69
+ pytest.param(
70
+ ("MetaTableSerializer",),
71
+ metatable_models.MetaTable,
72
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
73
+ id="meta-table",
74
+ ),
75
+ pytest.param(
76
+ ("MetaTableSerializer",),
77
+ metatable_models.TimeIndexMetaTable,
78
+ {ENVIRONMENT_UID_FIELD, ENVIRONMENT_NAME_FIELD},
79
+ id="time-index-meta-table",
80
+ ),
81
+ pytest.param(
82
+ ("SchedulerSerializer", "SchedulerMinimalSerializer"),
83
+ metatable_models.Scheduler,
84
+ {ENVIRONMENT_UID_FIELD},
85
+ id="scheduler",
86
+ ),
87
+ ],
88
+ )
89
+ def test_backend_environment_response_contract_is_declared_by_strict_sdk_model(
90
+ serializer_names,
91
+ model,
92
+ expected_fields,
93
+ ):
94
+ """Keep SDK response models aligned with ADR-0036/ADR-0037 projections."""
95
+ assert model.model_config.get("extra") == "forbid", serializer_names
96
+ assert expected_fields <= set(model.model_fields), serializer_names
@@ -0,0 +1,122 @@
1
+ import pytest
2
+ from pydantic import ValidationError
3
+
4
+ import mainsequence.client.metatables.core as core_mod
5
+
6
+ ENVIRONMENT_UID = "58218213-5e4e-43de-a5bd-6757f4e1c8f6"
7
+ SCHEDULER_UID = "00000000-0000-4000-8000-000000000001"
8
+ UPDATE_NODE_UID = "00000000-0000-4000-8000-000000000002"
9
+
10
+
11
+ def _scheduler_payload():
12
+ return {
13
+ "uid": SCHEDULER_UID,
14
+ "organization_project_environment_uid": ENVIRONMENT_UID,
15
+ "name": "tutorial",
16
+ "is_running": False,
17
+ "running_process_pid": None,
18
+ "running_in_debug_mode": True,
19
+ "updates_halted": False,
20
+ "host": None,
21
+ "api_address": None,
22
+ "api_port": None,
23
+ "last_heart_beat": None,
24
+ "pre_loads_in_tree": [],
25
+ "in_active_tree": [],
26
+ "schedules_to": [],
27
+ }
28
+
29
+
30
+ class _SchedulerResponse:
31
+ status_code = 200
32
+ text = ""
33
+
34
+ @staticmethod
35
+ def json():
36
+ return _scheduler_payload()
37
+
38
+ @staticmethod
39
+ def raise_for_status():
40
+ return None
41
+
42
+
43
+ def test_scheduler_strict_model_accepts_environment_projection():
44
+ scheduler = core_mod.Scheduler.model_validate(_scheduler_payload())
45
+
46
+ assert scheduler.organization_project_environment_uid == ENVIRONMENT_UID
47
+
48
+ with pytest.raises(ValidationError, match="unexpected_projection"):
49
+ core_mod.Scheduler.model_validate(
50
+ {**_scheduler_payload(), "unexpected_projection": "rejected"}
51
+ )
52
+
53
+
54
+ def test_scheduler_build_derives_environment_without_request_override(monkeypatch):
55
+ captured = {}
56
+
57
+ def _fake_make_request(**kwargs):
58
+ captured.update(kwargs)
59
+ return _SchedulerResponse()
60
+
61
+ monkeypatch.setattr(
62
+ core_mod.Scheduler,
63
+ "build_session",
64
+ classmethod(lambda cls: object()),
65
+ )
66
+ monkeypatch.setattr(core_mod, "make_request", _fake_make_request)
67
+
68
+ scheduler = core_mod.Scheduler.build_and_assign_to_update_nodes(
69
+ scheduler_name="tutorial",
70
+ update_node_uids=[UPDATE_NODE_UID],
71
+ timeout=11,
72
+ )
73
+
74
+ request_body = captured["payload"]["json"]
75
+ assert "organization_project_environment_uid" not in request_body
76
+ assert "organization_project_environment_uid" not in request_body["scheduler_kwargs"]
77
+ assert request_body["update_node_uids"] == [UPDATE_NODE_UID]
78
+ assert captured["time_out"] == 11
79
+ assert scheduler.organization_project_environment_uid == ENVIRONMENT_UID
80
+
81
+
82
+ def test_scheduler_get_for_update_node_accepts_environment_projection(monkeypatch):
83
+ captured = {}
84
+
85
+ def _fake_make_request(**kwargs):
86
+ captured.update(kwargs)
87
+ return _SchedulerResponse()
88
+
89
+ monkeypatch.setattr(
90
+ core_mod.Scheduler,
91
+ "build_session",
92
+ classmethod(lambda cls: object()),
93
+ )
94
+ monkeypatch.setattr(core_mod, "make_request", _fake_make_request)
95
+
96
+ scheduler = core_mod.Scheduler.get_scheduler_for_update_node(UPDATE_NODE_UID)
97
+
98
+ assert captured["r_type"] == "GET"
99
+ assert captured["payload"] == {"params": {"update_node_uid": UPDATE_NODE_UID}}
100
+ assert scheduler.organization_project_environment_uid == ENVIRONMENT_UID
101
+
102
+
103
+ def test_scheduler_assign_accepts_environment_projection(monkeypatch):
104
+ captured = {}
105
+ scheduler = core_mod.Scheduler.model_validate(_scheduler_payload())
106
+
107
+ def _fake_make_request(**kwargs):
108
+ captured.update(kwargs)
109
+ return _SchedulerResponse()
110
+
111
+ monkeypatch.setattr(
112
+ core_mod.Scheduler,
113
+ "build_session",
114
+ classmethod(lambda cls: object()),
115
+ )
116
+ monkeypatch.setattr(core_mod, "make_request", _fake_make_request)
117
+
118
+ assigned = scheduler.assign_to_scheduler([UPDATE_NODE_UID])
119
+
120
+ assert captured["r_type"] == "PATCH"
121
+ assert captured["payload"] == {"json": {"update_node_uids": [UPDATE_NODE_UID]}}
122
+ assert assigned.organization_project_environment_uid == ENVIRONMENT_UID
File without changes
File without changes
File without changes