mainsequence 4.1.4__tar.gz → 4.1.5__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.
- {mainsequence-4.1.4 → mainsequence-4.1.5}/PKG-INFO +1 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +7 -26
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/ms-markets/SKILL.md +2 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/cli.py +1 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/base.py +0 -1
- {mainsequence-4.1.4/mainsequence → mainsequence-4.1.5/mainsequence/client}/compute_validation.py +6 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/data_sources_interfaces/duckdb.py +2 -3
- mainsequence-4.1.5/mainsequence/client/data_sources_interfaces/local_paths.py +14 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/data_sources_interfaces/sqlite.py +2 -3
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/models_foundry.py +5 -4
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/models_helpers.py +2 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/logconf.py +22 -36
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/__init__.py +0 -9
- mainsequence-4.1.5/mainsequence/meta_tables/compiled_sql/__init__.py +5 -0
- mainsequence-4.1.4/mainsequence/meta_tables/compiled_sql.py → mainsequence-4.1.5/mainsequence/meta_tables/compiled_sql/v1.py +3 -3
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/runtime_flags.py +2 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/PKG-INFO +1 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/SOURCES.txt +4 -5
- {mainsequence-4.1.4 → mainsequence-4.1.5}/pyproject.toml +1 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_auth_precedence.py +5 -9
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_build_operations_hashing.py +5 -5
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_cli.py +1 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_data_access_mixin_dimension_audit.py +0 -55
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_data_node_storage_dimension_queries.py +0 -20
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_data_node_update_flow.py +0 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_duckdb_interface_dimensions.py +0 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_filter_normalization.py +0 -26
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_logconf.py +26 -11
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_meta_tables_client_models.py +4 -7
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -1
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_run_configuration.py +3 -7
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_source_table_configuration.py +1 -71
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_sqlite_interface_dimensions.py +0 -2
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_update_statistics.py +1 -4
- mainsequence-4.1.4/mainsequence/meta_tables/config.py +0 -128
- mainsequence-4.1.4/mainsequence/meta_tables/configuration_models.py +0 -5
- mainsequence-4.1.4/mainsequence/meta_tables/utils.py +0 -45
- {mainsequence-4.1.4 → mainsequence-4.1.5}/LICENSE +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/README.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/__main__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/bootstrap.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/api.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/config.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/cli/ui.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/client.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/connections.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/models_metatables.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/models_user.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/defaults.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/setup.cfg +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_client.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_command_center_data_models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_command_center_models.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_dependency_extras.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_secret_client_model.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_update_uid_guards.py +0 -0
- {mainsequence-4.1.4 → mainsequence-4.1.5}/tests/test_workspace_snapshot.py +0 -0
{mainsequence-4.1.4 → mainsequence-4.1.5}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md
RENAMED
|
@@ -30,8 +30,7 @@ Canonical workflow:
|
|
|
30
30
|
- `dependencies()`
|
|
31
31
|
- `update()`
|
|
32
32
|
- `prepare_update_statistics()`
|
|
33
|
-
|
|
34
|
-
- design single-index or `(time_index, unique_identifier)` DataFrame outputs
|
|
33
|
+
- design single-index or multidimensional time-first DataFrame outputs
|
|
35
34
|
- validate output shape against a `PlatformTimeIndexMetaData` storage contract
|
|
36
35
|
- define explicit `hash_namespace(...)` validation strategy
|
|
37
36
|
- write or review DataNode smoke tests
|
|
@@ -80,7 +79,6 @@ Before changing code, collect or infer:
|
|
|
80
79
|
- expected time index and identity index shape
|
|
81
80
|
- expected columns and dtypes from the storage class
|
|
82
81
|
- upstream dependencies
|
|
83
|
-
- whether the update is asset scoped
|
|
84
82
|
- first-run or backfill bounds
|
|
85
83
|
- whether the change must preserve the existing table contract
|
|
86
84
|
|
|
@@ -302,30 +300,19 @@ changing it changes the dependency graph and update identity.
|
|
|
302
300
|
|
|
303
301
|
Do not construct dependency graphs dynamically inside `update()`.
|
|
304
302
|
|
|
305
|
-
### 8.
|
|
306
|
-
|
|
307
|
-
If the node emits `(time_index, unique_identifier)`:
|
|
308
|
-
|
|
309
|
-
- `unique_identifier` should represent an Asset identity
|
|
310
|
-
- asset scope should live in update configuration when it affects the updater
|
|
311
|
-
- `get_asset_list()` must reflect the effective updater asset scope when the
|
|
312
|
-
workflow uses that hook
|
|
313
|
-
- missing assets should be resolved or registered by the relevant workflow
|
|
314
|
-
|
|
315
|
-
### 9. Foreign Keys Belong To The Storage Contract
|
|
303
|
+
### 8. Foreign Keys Belong To The Storage Contract
|
|
316
304
|
|
|
317
305
|
For new code, model foreign keys on the `PlatformTimeIndexMetaData` storage
|
|
318
306
|
class or route the storage-contract work to the MetaTable skill.
|
|
319
307
|
|
|
320
308
|
Do not add DataNode configuration fields just to mutate storage metadata.
|
|
321
309
|
|
|
322
|
-
###
|
|
310
|
+
### 9. Metadata Belongs To Storage
|
|
323
311
|
|
|
324
312
|
Production-quality table identifiers, descriptions, labels, column docs, and
|
|
325
313
|
foreign-key metadata belong to the storage class/MetaTable registration path.
|
|
326
314
|
|
|
327
|
-
Do not
|
|
328
|
-
surface for new DataNode work.
|
|
315
|
+
Do not put schema or published table metadata on the DataNode configuration.
|
|
329
316
|
|
|
330
317
|
## Review Rules
|
|
331
318
|
|
|
@@ -333,7 +320,7 @@ When reviewing an existing DataNode, look for:
|
|
|
333
320
|
|
|
334
321
|
- output storage contract hidden in `DataNodeConfiguration`
|
|
335
322
|
- dependency storage table passed as an ad hoc constructor argument
|
|
336
|
-
-
|
|
323
|
+
- schema or published table metadata hidden in DataNode configuration
|
|
337
324
|
- `update_only`, `runtime_only`, or `ignore_from_storage_hash`
|
|
338
325
|
- `test_node=True`
|
|
339
326
|
- missing explicit `storage_table`
|
|
@@ -342,7 +329,7 @@ When reviewing an existing DataNode, look for:
|
|
|
342
329
|
- misuse of `hash_namespace`
|
|
343
330
|
- non-incremental `update()` behavior
|
|
344
331
|
- hidden dependency creation inside `update()`
|
|
345
|
-
- invalid
|
|
332
|
+
- invalid identity-indexed output shape
|
|
346
333
|
- `time_index` dtype that is not exactly `datetime64[ns, UTC]`
|
|
347
334
|
- DataFrame columns that do not match the `PlatformTimeIndexMetaData` class
|
|
348
335
|
|
|
@@ -363,17 +350,11 @@ Do not claim success until you have checked:
|
|
|
363
350
|
- non-empty outputs have first index level `time_index` with dtype `datetime64[ns, UTC]`
|
|
364
351
|
- the first validation run uses explicit `hash_namespace(...)` when it touches a shared backend
|
|
365
352
|
|
|
366
|
-
For asset-scoped updates, also check:
|
|
367
|
-
|
|
368
|
-
- `get_asset_list()` is correct when used
|
|
369
|
-
- no duplicate `(time_index, unique_identifier)` rows are emitted
|
|
370
|
-
- assets exist or are registered idempotently when needed
|
|
371
|
-
|
|
372
353
|
## This Skill Must Stop And Escalate When
|
|
373
354
|
|
|
374
355
|
- the change may break an existing published table contract and the versioning decision is unclear
|
|
375
356
|
- the intended storage class or MetaTable registration path is unclear
|
|
376
|
-
- the node needs
|
|
357
|
+
- the node needs identity dimensions but the coordinate strategy is unclear
|
|
377
358
|
- the task is actually an API, MetaTable, orchestration, or sharing problem
|
|
378
359
|
- docs, skill instructions, and code disagree on hashing or runtime behavior
|
|
379
360
|
|
|
@@ -6,8 +6,8 @@ description: Use this skill when a Main Sequence project needs financial markets
|
|
|
6
6
|
# Main Sequence ms-markets
|
|
7
7
|
|
|
8
8
|
`ms-markets` is the Main Sequence supported library for financial markets workflows.
|
|
9
|
-
Use it for market assets, market MetaTables,
|
|
10
|
-
|
|
9
|
+
Use it for market assets, market MetaTables, portfolios, orders, trades, and
|
|
10
|
+
related market-domain APIs.
|
|
11
11
|
|
|
12
12
|
This SDK scaffold skill is intentionally tiny. It does not own market-domain
|
|
13
13
|
implementation rules. Install `ms-markets` and copy its packaged skills into the
|
|
@@ -45,7 +45,7 @@ import click
|
|
|
45
45
|
import typer
|
|
46
46
|
import yaml
|
|
47
47
|
|
|
48
|
-
from ..compute_validation import decimal_to_storage, parse_cpu_request, parse_memory_request
|
|
48
|
+
from ..client.compute_validation import decimal_to_storage, parse_cpu_request, parse_memory_request
|
|
49
49
|
from . import config as cfg
|
|
50
50
|
from .api import (
|
|
51
51
|
ApiError,
|
|
@@ -84,7 +84,6 @@ class BaseObjectOrm:
|
|
|
84
84
|
"MultiIndexMetadata": "orm/multi_index_metadata",
|
|
85
85
|
"ContinuousAggMultiIndex": "ts_manager/cont_agg_multi_ind",
|
|
86
86
|
"TimeIndexMetaData": "ts_manager/dynamic_table",
|
|
87
|
-
# "LocalTimeSerieNodesMethods": "ogm/local_time_serie",
|
|
88
87
|
"LocalTimeSerieNodesMethods": "ts_manager/local_time_serie",
|
|
89
88
|
"DataNodeUpdate": "ts_manager/local_time_serie",
|
|
90
89
|
"DataNodeUpdateDetails": "ts_manager/local_time_serie_update_details",
|
{mainsequence-4.1.4/mainsequence → mainsequence-4.1.5/mainsequence/client}/compute_validation.py
RENAMED
|
@@ -114,7 +114,9 @@ def parse_gpu_request(value: Any, *, field_name: str = "gpu_request") -> int | N
|
|
|
114
114
|
raise ValueError(f"{field_name} must be a valid integer.") from exc
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
def format_cpu_request(
|
|
117
|
+
def format_cpu_request(
|
|
118
|
+
value: Decimal | None, *, output_format: Literal["decimal", "k8s"] = "decimal"
|
|
119
|
+
) -> str | None:
|
|
118
120
|
if value is None:
|
|
119
121
|
return None
|
|
120
122
|
if output_format == "decimal":
|
|
@@ -129,7 +131,9 @@ def format_cpu_request(value: Decimal | None, *, output_format: Literal["decimal
|
|
|
129
131
|
return decimal_to_storage(value)
|
|
130
132
|
|
|
131
133
|
|
|
132
|
-
def format_memory_request(
|
|
134
|
+
def format_memory_request(
|
|
135
|
+
value: Decimal | None, *, output_format: Literal["decimal", "k8s"] = "decimal"
|
|
136
|
+
) -> str | None:
|
|
133
137
|
if value is None:
|
|
134
138
|
return None
|
|
135
139
|
if output_format == "decimal":
|
{mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/data_sources_interfaces/duckdb.py
RENAMED
|
@@ -23,6 +23,7 @@ from ..dtype_codec import (
|
|
|
23
23
|
token_to_pandas_series,
|
|
24
24
|
)
|
|
25
25
|
from ..utils import DataFrequency
|
|
26
|
+
from .local_paths import local_data_path
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
def get_logger():
|
|
@@ -53,12 +54,10 @@ class DuckDBInterface:
|
|
|
53
54
|
environment variable or 'analytics.duckdb'
|
|
54
55
|
in the current directory if the variable is not set.
|
|
55
56
|
"""
|
|
56
|
-
from mainsequence.meta_tables.config import META_TABLES_DATA_PATH
|
|
57
|
-
|
|
58
57
|
# ── choose default & normalise to string ───────────────────────────
|
|
59
58
|
default_path = os.getenv(
|
|
60
59
|
"DUCKDB_PATH",
|
|
61
|
-
os.
|
|
60
|
+
os.fspath(local_data_path() / "duck_db"),
|
|
62
61
|
)
|
|
63
62
|
db_uri = str(db_path or default_path).rstrip("/")
|
|
64
63
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def local_data_path() -> Path:
|
|
8
|
+
configured = (os.getenv("MAINSEQUENCE_LOCAL_DATA_PATH") or "").strip()
|
|
9
|
+
if configured:
|
|
10
|
+
return Path(configured).expanduser()
|
|
11
|
+
return Path.home() / "meta_tables" / "data"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
__all__ = ["local_data_path"]
|
{mainsequence-4.1.4 → mainsequence-4.1.5}/mainsequence/client/data_sources_interfaces/sqlite.py
RENAMED
|
@@ -16,6 +16,7 @@ from ..dtype_codec import (
|
|
|
16
16
|
token_to_backend_type,
|
|
17
17
|
token_to_pandas_series,
|
|
18
18
|
)
|
|
19
|
+
from .local_paths import local_data_path
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def get_logger():
|
|
@@ -32,11 +33,9 @@ class SQLiteInterface:
|
|
|
32
33
|
"""
|
|
33
34
|
|
|
34
35
|
def __init__(self, db_path: str | Path | None = None):
|
|
35
|
-
from mainsequence.meta_tables.config import META_TABLES_DATA_PATH
|
|
36
|
-
|
|
37
36
|
default_path = os.getenv(
|
|
38
37
|
"SQLITE_PATH",
|
|
39
|
-
os.
|
|
38
|
+
os.fspath(local_data_path() / "sqlite"),
|
|
40
39
|
)
|
|
41
40
|
raw_path = Path(str(db_path or default_path)).expanduser()
|
|
42
41
|
if raw_path.suffix in {".db", ".sqlite", ".sqlite3"}:
|
|
@@ -760,10 +760,11 @@ def add_created_object_to_jobrun(
|
|
|
760
760
|
Returns:
|
|
761
761
|
A dictionary representing the created record.
|
|
762
762
|
"""
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
763
|
+
job_run_uid = (os.getenv("JOB_RUN_UID") or "").strip()
|
|
764
|
+
if not job_run_uid:
|
|
765
|
+
raise RuntimeError("JOB_RUN_UID is required to attach created objects to a job run.")
|
|
766
|
+
|
|
767
|
+
url = MAINSEQUENCE_ENDPOINT + f"/orm/api/pods/job-run/{job_run_uid}/add_created_object/"
|
|
767
768
|
payload = {"json": {"app_label": app_label, "model_name": model_name, "object_id": object_id}}
|
|
768
769
|
|
|
769
770
|
r = make_request(
|
|
@@ -13,12 +13,12 @@ from uuid import UUID
|
|
|
13
13
|
import yaml
|
|
14
14
|
from pydantic import BaseModel, Field, PositiveInt
|
|
15
15
|
|
|
16
|
-
from
|
|
16
|
+
from .base import BaseObjectOrm, BasePydanticModel, ShareableObjectMixin
|
|
17
|
+
from .compute_validation import (
|
|
17
18
|
decimal_to_storage,
|
|
18
19
|
normalize_string,
|
|
19
20
|
validate_and_normalize_compute_fields,
|
|
20
21
|
)
|
|
21
|
-
from .base import BaseObjectOrm, BasePydanticModel, ShareableObjectMixin
|
|
22
22
|
from .exceptions import raise_for_response
|
|
23
23
|
from .models_foundry import (
|
|
24
24
|
Project,
|
|
@@ -71,7 +71,7 @@ class CustomConsoleRenderer(ConsoleRenderer):
|
|
|
71
71
|
|
|
72
72
|
def _request_job_startup_state(*, timeout_s: float = 10.0) -> dict[str, Any]:
|
|
73
73
|
"""
|
|
74
|
-
Fetch startup state from backend using current env vars (JWT auth, endpoint,
|
|
74
|
+
Fetch startup state from backend using current env vars (JWT auth, endpoint, job_run_uid).
|
|
75
75
|
Safe to call later after auth when access/refresh tokens become available.
|
|
76
76
|
"""
|
|
77
77
|
if not is_running_in_pod():
|
|
@@ -183,16 +183,12 @@ def _request_job_startup_state(*, timeout_s: float = 10.0) -> dict[str, Any]:
|
|
|
183
183
|
|
|
184
184
|
headers, using_jwt = _auth_headers()
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
if not
|
|
186
|
+
job_run_uid = (os.getenv("JOB_RUN_UID") or "").strip()
|
|
187
|
+
if not job_run_uid:
|
|
188
188
|
return {}
|
|
189
189
|
|
|
190
|
-
endpoint = f"{_backend_base_url()}/orm/api/pods/job-run/{
|
|
191
|
-
|
|
192
|
-
command_id = os.getenv("COMMAND_ID")
|
|
190
|
+
endpoint = f"{_backend_base_url()}/orm/api/pods/job-run/{job_run_uid}/startup-state/"
|
|
193
191
|
params: dict[str, Any] = {}
|
|
194
|
-
if command_id:
|
|
195
|
-
params["command_id"] = command_id
|
|
196
192
|
|
|
197
193
|
resp = requests.get(endpoint, headers=headers, params=params, timeout=timeout_s)
|
|
198
194
|
if resp.status_code in {401, 403} and using_jwt and _refresh_access_token():
|
|
@@ -225,8 +221,6 @@ def _apply_additional_environment(startup_state: Mapping[str, Any]) -> None:
|
|
|
225
221
|
|
|
226
222
|
def _build_backend_bindings(
|
|
227
223
|
startup_state: Mapping[str, Any],
|
|
228
|
-
*,
|
|
229
|
-
command_id: str | None = None,
|
|
230
224
|
) -> dict[str, Any]:
|
|
231
225
|
"""
|
|
232
226
|
Pure function: compute the keys you want to bind on the logger
|
|
@@ -243,10 +237,8 @@ def _build_backend_bindings(
|
|
|
243
237
|
bindings["project_id"] = project_id
|
|
244
238
|
bindings["data_source_id"] = startup_state.get("data_source_id")
|
|
245
239
|
bindings["job_run_id"] = startup_state.get("job_run_id")
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
command_id = os.getenv("COMMAND_ID")
|
|
249
|
-
bindings["command_id"] = int(command_id) if command_id else None
|
|
240
|
+
bindings["job_run_uid"] = startup_state.get("job_run_uid")
|
|
241
|
+
bindings["command_id"] = startup_state.get("command_id")
|
|
250
242
|
else:
|
|
251
243
|
# your existing behavior: bind job_run_id to user_id in local-ish mode
|
|
252
244
|
if "user_id" in startup_state:
|
|
@@ -276,14 +268,12 @@ def _bind_runtime(logger_: BoundLogger, **bindings: Any) -> BoundLogger:
|
|
|
276
268
|
def apply_startup_state_bindings(
|
|
277
269
|
logger_: BoundLogger,
|
|
278
270
|
startup_state: Mapping[str, Any],
|
|
279
|
-
*,
|
|
280
|
-
command_id: str | None = None,
|
|
281
271
|
) -> BoundLogger:
|
|
282
272
|
"""
|
|
283
273
|
Apply env + bindings derived from startup_state to the given logger.
|
|
284
274
|
"""
|
|
285
275
|
_apply_additional_environment(startup_state)
|
|
286
|
-
binds = _build_backend_bindings(startup_state
|
|
276
|
+
binds = _build_backend_bindings(startup_state)
|
|
287
277
|
return _bind_runtime(logger_, **binds)
|
|
288
278
|
|
|
289
279
|
|
|
@@ -295,7 +285,6 @@ def build_application_logger(application_name: str = "ms-sdk", **metadata):
|
|
|
295
285
|
"""
|
|
296
286
|
|
|
297
287
|
# do initial request when on logger initialization
|
|
298
|
-
command_id = os.getenv("COMMAND_ID")
|
|
299
288
|
json_response = _request_job_startup_state()
|
|
300
289
|
|
|
301
290
|
# set additional args from backend
|
|
@@ -341,22 +330,22 @@ def build_application_logger(application_name: str = "ms-sdk", **metadata):
|
|
|
341
330
|
}
|
|
342
331
|
else:
|
|
343
332
|
handlers["console"] = {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
333
|
+
"class": "logging.StreamHandler",
|
|
334
|
+
"formatter": "colored",
|
|
335
|
+
"level": os.getenv("LOG_LEVEL", "DEBUG"),
|
|
347
336
|
}
|
|
348
337
|
|
|
349
338
|
if logger_file is not None:
|
|
350
339
|
ensure_dir(logger_file) # Ensure the directory for the log file exists
|
|
351
340
|
handlers["file"] = {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
341
|
+
"class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
|
|
342
|
+
"formatter": "plain",
|
|
343
|
+
"level": os.getenv("LOG_LEVEL_FILE", "DEBUG"),
|
|
344
|
+
"filename": logger_file,
|
|
345
|
+
"mode": "a",
|
|
346
|
+
"delay": True,
|
|
347
|
+
"maxBytes": 5 * 1024 * 1024, # Rotate after 5 MB
|
|
348
|
+
"backupCount": 5, # Keep up to 5 backup files
|
|
360
349
|
}
|
|
361
350
|
|
|
362
351
|
logging_config = {
|
|
@@ -421,20 +410,17 @@ def build_application_logger(application_name: str = "ms-sdk", **metadata):
|
|
|
421
410
|
)
|
|
422
411
|
|
|
423
412
|
try:
|
|
424
|
-
|
|
425
|
-
backend_binds = _build_backend_bindings(json_response, command_id=command_id)
|
|
413
|
+
backend_binds = _build_backend_bindings(json_response)
|
|
426
414
|
logger = _bind_runtime(logger, **backend_binds)
|
|
427
415
|
|
|
428
|
-
|
|
429
|
-
|
|
430
416
|
except Exception:
|
|
431
|
-
|
|
432
417
|
logger.exception("Logger could not be binded running in local mode")
|
|
433
418
|
logger = logger.bind(local_mode="no_app", **metadata)
|
|
434
419
|
|
|
435
420
|
logger = logger.bind()
|
|
436
421
|
return logger
|
|
437
422
|
|
|
423
|
+
|
|
438
424
|
def refresh_application_logger_bindings(*, timeout_s: float = 10.0) -> BoundLogger:
|
|
439
425
|
"""
|
|
440
426
|
Importable helper: call this AFTER the user authenticates / token exists.
|
|
@@ -442,13 +428,12 @@ def refresh_application_logger_bindings(*, timeout_s: float = 10.0) -> BoundLogg
|
|
|
442
428
|
"""
|
|
443
429
|
global logger
|
|
444
430
|
|
|
445
|
-
command_id = os.getenv("COMMAND_ID")
|
|
446
431
|
json_response = _request_job_startup_state(timeout_s=timeout_s)
|
|
447
432
|
|
|
448
433
|
# set additional args from backend
|
|
449
434
|
_apply_additional_environment(json_response)
|
|
450
435
|
|
|
451
|
-
backend_binds = _build_backend_bindings(json_response
|
|
436
|
+
backend_binds = _build_backend_bindings(json_response)
|
|
452
437
|
|
|
453
438
|
# if somebody calls this super early
|
|
454
439
|
if logger is None:
|
|
@@ -458,6 +443,7 @@ def refresh_application_logger_bindings(*, timeout_s: float = 10.0) -> BoundLogg
|
|
|
458
443
|
logger = _bind_runtime(logger, **backend_binds)
|
|
459
444
|
return logger
|
|
460
445
|
|
|
446
|
+
|
|
461
447
|
def dump_structlog_bound_logger(logger: BoundLogger) -> dict[str, Any]:
|
|
462
448
|
"""
|
|
463
449
|
Serialize a fully‑initialized structlog BoundLogger into a dict:
|
|
@@ -5,10 +5,6 @@ from importlib import import_module
|
|
|
5
5
|
from mainsequence.instrumentation import TracerInstrumentator
|
|
6
6
|
|
|
7
7
|
_LAZY_IMPORTS = {
|
|
8
|
-
"TIME_SERIES_SOURCE_TIMESCALE": (".config", "TIME_SERIES_SOURCE_TIMESCALE"),
|
|
9
|
-
"RunningMode": (".config", "RunningMode"),
|
|
10
|
-
"configuration": (".config", "configuration"),
|
|
11
|
-
"ogm": (".config", "ogm"),
|
|
12
8
|
"DEFAULT_PLATFORM_MANAGED_PROVISIONING": (
|
|
13
9
|
".sqlalchemy_contracts",
|
|
14
10
|
"DEFAULT_PLATFORM_MANAGED_PROVISIONING",
|
|
@@ -20,16 +16,11 @@ _LAZY_IMPORTS = {
|
|
|
20
16
|
"APIDataNode": (".data_nodes", "APIDataNode"),
|
|
21
17
|
"DataNode": (".data_nodes", "DataNode"),
|
|
22
18
|
"DataNodeConfiguration": (".data_nodes", "DataNodeConfiguration"),
|
|
23
|
-
"build_compiled_sql_v1_operation": (
|
|
24
|
-
".compiled_sql",
|
|
25
|
-
"build_compiled_sql_v1_operation",
|
|
26
|
-
),
|
|
27
19
|
"build_meta_table_configured_storage_hash": (
|
|
28
20
|
".hashing",
|
|
29
21
|
"build_meta_table_configured_storage_hash",
|
|
30
22
|
),
|
|
31
23
|
"build_meta_table_storage_hash": (".hashing", "build_meta_table_storage_hash"),
|
|
32
|
-
"compile_sqlalchemy_statement": (".compiled_sql", "compile_sqlalchemy_statement"),
|
|
33
24
|
"external_registered_registration_request_from_sqlalchemy_model": (
|
|
34
25
|
".sqlalchemy_contracts",
|
|
35
26
|
"external_registered_registration_request_from_sqlalchemy_model",
|
|
@@ -17,7 +17,7 @@ from mainsequence.client.models_metatables import (
|
|
|
17
17
|
)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def
|
|
20
|
+
def build_operation(
|
|
21
21
|
*,
|
|
22
22
|
operation: MetaTableOperation,
|
|
23
23
|
sql: str,
|
|
@@ -115,7 +115,7 @@ def compile_sqlalchemy_statement(
|
|
|
115
115
|
for table in scope_tables
|
|
116
116
|
]
|
|
117
117
|
)
|
|
118
|
-
return
|
|
118
|
+
return build_operation(
|
|
119
119
|
operation=operation,
|
|
120
120
|
sql=str(compiled),
|
|
121
121
|
parameters=dict(compiled.params),
|
|
@@ -143,6 +143,6 @@ def _compiled_sqlalchemy_parameter_types(compiled: Any) -> dict[str, str]:
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
__all__ = [
|
|
146
|
-
"
|
|
146
|
+
"build_operation",
|
|
147
147
|
"compile_sqlalchemy_statement",
|
|
148
148
|
]
|
|
@@ -7,8 +7,8 @@ def is_running_in_pod() -> bool:
|
|
|
7
7
|
"""
|
|
8
8
|
Return whether the current process is running inside a MainSequence pod.
|
|
9
9
|
|
|
10
|
-
Pod runtime is identified by
|
|
10
|
+
Pod runtime is identified by the job-run UID injected by the platform.
|
|
11
11
|
Local workspaces may also set `MAIN_SEQUENCE_PROJECT_ID`, so that variable
|
|
12
12
|
must not be used as the pod-runtime discriminator.
|
|
13
13
|
"""
|
|
14
|
-
return bool((os.getenv("
|
|
14
|
+
return bool((os.getenv("JOB_RUN_UID") or "").strip())
|
|
@@ -24,7 +24,6 @@ agent_scaffold/skills/project_to_agent/SKILL.md
|
|
|
24
24
|
mainsequence/__init__.py
|
|
25
25
|
mainsequence/__main__.py
|
|
26
26
|
mainsequence/bootstrap.py
|
|
27
|
-
mainsequence/compute_validation.py
|
|
28
27
|
mainsequence/defaults.py
|
|
29
28
|
mainsequence/logconf.py
|
|
30
29
|
mainsequence/runtime_flags.py
|
|
@@ -52,6 +51,7 @@ mainsequence/client/__init__.py
|
|
|
52
51
|
mainsequence/client/agent_runtime_models.py
|
|
53
52
|
mainsequence/client/base.py
|
|
54
53
|
mainsequence/client/client.py
|
|
54
|
+
mainsequence/client/compute_validation.py
|
|
55
55
|
mainsequence/client/dtype_codec.py
|
|
56
56
|
mainsequence/client/exceptions.py
|
|
57
57
|
mainsequence/client/models_foundry.py
|
|
@@ -67,6 +67,7 @@ mainsequence/client/command_center/workspace.py
|
|
|
67
67
|
mainsequence/client/command_center/workspace_snapshot.py
|
|
68
68
|
mainsequence/client/data_sources_interfaces/__init__.py
|
|
69
69
|
mainsequence/client/data_sources_interfaces/duckdb.py
|
|
70
|
+
mainsequence/client/data_sources_interfaces/local_paths.py
|
|
70
71
|
mainsequence/client/data_sources_interfaces/sqlite.py
|
|
71
72
|
mainsequence/client/fastapi/__init__.py
|
|
72
73
|
mainsequence/client/fastapi/auth.py
|
|
@@ -74,14 +75,12 @@ mainsequence/instrumentation/__init__.py
|
|
|
74
75
|
mainsequence/instrumentation/utils.py
|
|
75
76
|
mainsequence/meta_tables/__init__.py
|
|
76
77
|
mainsequence/meta_tables/__main__.py
|
|
77
|
-
mainsequence/meta_tables/compiled_sql.py
|
|
78
|
-
mainsequence/meta_tables/config.py
|
|
79
|
-
mainsequence/meta_tables/configuration_models.py
|
|
80
78
|
mainsequence/meta_tables/future_registry.py
|
|
81
79
|
mainsequence/meta_tables/hashing.py
|
|
82
80
|
mainsequence/meta_tables/pydantic_metadata.py
|
|
83
81
|
mainsequence/meta_tables/sqlalchemy_contracts.py
|
|
84
|
-
mainsequence/meta_tables/
|
|
82
|
+
mainsequence/meta_tables/compiled_sql/__init__.py
|
|
83
|
+
mainsequence/meta_tables/compiled_sql/v1.py
|
|
85
84
|
mainsequence/meta_tables/data_nodes/__init__.py
|
|
86
85
|
mainsequence/meta_tables/data_nodes/build_operations.py
|
|
87
86
|
mainsequence/meta_tables/data_nodes/data_nodes.py
|
|
@@ -88,8 +88,7 @@ def test_auth_loaders_build_headers_from_env_jwt(monkeypatch):
|
|
|
88
88
|
def test_logconf_refreshes_jwt_before_startup_state_request(monkeypatch):
|
|
89
89
|
monkeypatch.delenv("MAINSEQUENCE_ACCESS_TOKEN", raising=False)
|
|
90
90
|
monkeypatch.setenv("MAINSEQUENCE_REFRESH_TOKEN", "jwt-refresh")
|
|
91
|
-
monkeypatch.setenv("
|
|
92
|
-
monkeypatch.setenv("JOB_RUN_ID", "34")
|
|
91
|
+
monkeypatch.setenv("JOB_RUN_UID", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")
|
|
93
92
|
monkeypatch.setenv("MAINSEQUENCE_ENDPOINT", "https://backend.example")
|
|
94
93
|
|
|
95
94
|
get_calls: list[dict] = []
|
|
@@ -119,8 +118,7 @@ def test_logconf_runtime_credential_exchanges_before_startup_state_request(monke
|
|
|
119
118
|
monkeypatch.setenv("MAINSEQUENCE_AUTH_MODE", "runtime_credential")
|
|
120
119
|
monkeypatch.setenv("MAINSEQUENCE_RUNTIME_CREDENTIAL_ID", "cred-id")
|
|
121
120
|
monkeypatch.setenv("MAINSEQUENCE_RUNTIME_CREDENTIAL_SECRET", "cred-secret")
|
|
122
|
-
monkeypatch.setenv("
|
|
123
|
-
monkeypatch.setenv("JOB_RUN_ID", "34")
|
|
121
|
+
monkeypatch.setenv("JOB_RUN_UID", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")
|
|
124
122
|
monkeypatch.setenv("MAINSEQUENCE_ENDPOINT", "https://backend.example")
|
|
125
123
|
|
|
126
124
|
get_calls: list[dict] = []
|
|
@@ -161,8 +159,7 @@ def test_logconf_runtime_credential_retries_after_auth_failure(monkeypatch):
|
|
|
161
159
|
monkeypatch.setenv("MAINSEQUENCE_AUTH_MODE", "runtime_credential")
|
|
162
160
|
monkeypatch.setenv("MAINSEQUENCE_RUNTIME_CREDENTIAL_ID", "cred-id")
|
|
163
161
|
monkeypatch.setenv("MAINSEQUENCE_RUNTIME_CREDENTIAL_SECRET", "cred-secret")
|
|
164
|
-
monkeypatch.setenv("
|
|
165
|
-
monkeypatch.setenv("JOB_RUN_ID", "34")
|
|
162
|
+
monkeypatch.setenv("JOB_RUN_UID", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")
|
|
166
163
|
monkeypatch.setenv("MAINSEQUENCE_ENDPOINT", "https://backend.example")
|
|
167
164
|
|
|
168
165
|
get_calls: list[dict] = []
|
|
@@ -499,8 +496,7 @@ def test_logconf_session_jwt_does_not_refresh(monkeypatch):
|
|
|
499
496
|
monkeypatch.setenv("MAINSEQUENCE_ACCESS_TOKEN", "runtime-access")
|
|
500
497
|
monkeypatch.delenv("MAINSEQUENCE_REFRESH_TOKEN", raising=False)
|
|
501
498
|
monkeypatch.setenv("MAINSEQUENCE_AUTH_MODE", "session_jwt")
|
|
502
|
-
monkeypatch.setenv("
|
|
503
|
-
monkeypatch.setenv("COMMAND_ID", "12")
|
|
499
|
+
monkeypatch.setenv("JOB_RUN_UID", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")
|
|
504
500
|
monkeypatch.setenv("MAINSEQUENCE_ENDPOINT", "https://backend.example")
|
|
505
501
|
|
|
506
502
|
get_calls: list[dict] = []
|
|
@@ -528,7 +524,7 @@ def test_logconf_session_jwt_rejects_refresh_token(monkeypatch):
|
|
|
528
524
|
monkeypatch.delenv("MAINSEQUENCE_ACCESS_TOKEN", raising=False)
|
|
529
525
|
monkeypatch.setenv("MAINSEQUENCE_REFRESH_TOKEN", "bad-refresh")
|
|
530
526
|
monkeypatch.setenv("MAINSEQUENCE_AUTH_MODE", "session_jwt")
|
|
531
|
-
monkeypatch.setenv("
|
|
527
|
+
monkeypatch.setenv("JOB_RUN_UID", "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa")
|
|
532
528
|
|
|
533
529
|
try:
|
|
534
530
|
_load_mainsequence_submodule("mainsequence.logconf")
|
|
@@ -264,18 +264,18 @@ def test_plain_dict_with_pydantic_model_import_path_key_is_not_treated_as_wrappe
|
|
|
264
264
|
assert build_operations.hash_signature(payload_a) != build_operations.hash_signature(payload_b)
|
|
265
265
|
|
|
266
266
|
|
|
267
|
-
def
|
|
268
|
-
class
|
|
267
|
+
def test_removed_storage_hash_metadata_is_rejected():
|
|
268
|
+
class RemovedStorageHashConfig(BaseModel):
|
|
269
269
|
shard_id: str = Field(..., json_schema_extra={"ignore_from_storage_hash": True})
|
|
270
270
|
|
|
271
271
|
with pytest.raises(ValueError, match="ignore_from_storage_hash"):
|
|
272
|
-
build_operations.serialize_argument(
|
|
272
|
+
build_operations.serialize_argument(RemovedStorageHashConfig(shard_id="desk_a"))
|
|
273
273
|
|
|
274
274
|
|
|
275
|
-
def
|
|
275
|
+
def test_removed_storage_hash_class_attribute_is_rejected():
|
|
276
276
|
with pytest.raises(TypeError, match="_ARGS_IGNORE_IN_STORAGE_HASH"):
|
|
277
277
|
|
|
278
|
-
class
|
|
278
|
+
class RemovedStorageHashDataNode(DataNode):
|
|
279
279
|
_ARGS_IGNORE_IN_STORAGE_HASH = ["asset_list"]
|
|
280
280
|
|
|
281
281
|
def __init__(self, *args, **kwargs):
|
|
@@ -1820,7 +1820,7 @@ def test_model_filter_parser_uses_filterset_metadata():
|
|
|
1820
1820
|
|
|
1821
1821
|
|
|
1822
1822
|
def test_shared_compute_validation_supports_k8s_quantities(cli_mod):
|
|
1823
|
-
compute_mod = importlib.import_module("mainsequence.compute_validation")
|
|
1823
|
+
compute_mod = importlib.import_module("mainsequence.client.compute_validation")
|
|
1824
1824
|
|
|
1825
1825
|
decimal_out = compute_mod.validate_and_normalize_compute_fields(
|
|
1826
1826
|
cpu_request="500m",
|