mainsequence 3.18.4__tar.gz → 3.18.6__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-3.18.4 → mainsequence-3.18.6}/PKG-INFO +1 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/cli.py +7 -8
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/config.py +4 -2
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/client.py +3 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/workspace_snapshot.py +3 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/models_simple_tables.py +7 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/models_tdag.py +7 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/models_user.py +2 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/utils.py +4 -3
- mainsequence-3.18.6/mainsequence/defaults.py +3 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/logconf.py +2 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/PKG-INFO +1 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/SOURCES.txt +1 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/pyproject.toml +1 -1
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_cli.py +78 -16
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_run_configuration.py +71 -2
- {mainsequence-3.18.4 → mainsequence-3.18.6}/LICENSE +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/README.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/data_publishing/simple_tables/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/maintenance/local_journal/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/markets_platform/assets_and_translation/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/markets_platform/instruments_and_pricing/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/markets_platform/virtualfundbuilder/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/__main__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/bootstrap.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/api.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/project_status.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/cli/ui.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/agent.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/agent_runtime_models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/base.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/app_component.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/data_models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/workspace.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/data_sources_interfaces/timescale.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/fastapi/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/fastapi/auth.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/models_vam.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/compute_validation.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/config.toml +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/favicon.png +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/image_1_base64.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/image_2_base64.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/image_3_base64.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/image_4_base64.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/image_5_base64.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/assets/logo.png +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/components/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/components/asset_select.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/components/date_settings.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/components/logged_user.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/core/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/core/theme.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/instruments/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/instruments/streamlit_form_factory.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/pages/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/dashboards/streamlit/scaffold.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/data_interface/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/data_interface/data_interface.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/base_instrument.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/bond.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/callability.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/interest_rate_swap.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/json_codec.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/position.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/instruments/ql_fields.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/interest_rates/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/interest_rates/etl/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/interest_rates/etl/curve_codec.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/interest_rates/etl/nodes.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/interest_rates/etl/registry.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/pricing_models/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/pricing_models/bond_pricer.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/pricing_models/indices.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/pricing_models/indices_builders.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/pricing_models/swap_pricer.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/settings.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/instruments/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/__main__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/base_persist_managers.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/config.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/configuration_models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/build_operations.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/data_nodes.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/filters.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/namespacing.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/persist_managers.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/run_operations.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/data_nodes/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/filters.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/future_registry.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/pydantic_metadata.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/filters.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/persist_managers.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/schema.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/simple_tables/table_nodes.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/tdag/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/external_weights.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/intraday_trend.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/market_cap.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/mock_signal.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/data_nodes/portfolio_replicator.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/prices/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/prices/data_nodes.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/prices/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/rebalance_strategies/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/contrib/rebalance_strategies/rebalance_strategies.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/enums.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/portfolio_nodes.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/resource_factory/__init__.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/resource_factory/rebalance_factory.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/resource_factory/signal_factory.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/virtualfundbuilder/utils.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/setup.cfg +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_auth_precedence.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_build_operations_hashing.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_client.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_command_center_app_component_models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_command_center_models.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_dependency_extras.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_filter_normalization.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_instruments.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_logconf.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_logged_user_components.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_project_batch_jobs_from_file.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_simple_tables_configuration_hashing.py +0 -0
- {mainsequence-3.18.4 → mainsequence-3.18.6}/tests/test_simple_tables_persistence.py +0 -0
|
@@ -226,7 +226,6 @@ from .ssh_utils import (
|
|
|
226
226
|
from .ui import error, info, print_kv, print_table, status, success, warn
|
|
227
227
|
|
|
228
228
|
JSON_OUTPUT_CONTEXT_KEY = "json_output"
|
|
229
|
-
LOGIN_DEFAULT_BACKEND_URL = "https://api.main-sequence.io"
|
|
230
229
|
|
|
231
230
|
|
|
232
231
|
class MainSequenceGroup(typer.core.TyperGroup):
|
|
@@ -2057,7 +2056,7 @@ def login(
|
|
|
2057
2056
|
Persists auth tokens in the active CLI auth store so subsequent
|
|
2058
2057
|
CLI invocations can run without re-authentication. Backend/base-folder
|
|
2059
2058
|
overrides passed to `login` are scoped to the current terminal session.
|
|
2060
|
-
When no backend is provided, login defaults to
|
|
2059
|
+
When no backend is provided, login defaults to the standard production backend.
|
|
2061
2060
|
|
|
2062
2061
|
Interactive login uses browser-based authentication and finishes with
|
|
2063
2062
|
standard JWT access/refresh tokens persisted by the CLI.
|
|
@@ -2122,7 +2121,7 @@ def login(
|
|
|
2122
2121
|
error("Pass backend either positionally or with --backend, not both.")
|
|
2123
2122
|
raise typer.Exit(1)
|
|
2124
2123
|
explicit_backend_input = backend_option if backend_option is not None else backend
|
|
2125
|
-
effective_backend_input = explicit_backend_input if explicit_backend_input is not None else
|
|
2124
|
+
effective_backend_input = explicit_backend_input if explicit_backend_input is not None else cfg.STANDARD_BACKEND_URL
|
|
2126
2125
|
|
|
2127
2126
|
if projects_base and projects_base_option:
|
|
2128
2127
|
if cfg.normalize_mainsequence_path(projects_base) != cfg.normalize_mainsequence_path(projects_base_option):
|
|
@@ -2873,7 +2872,7 @@ def settings_set_base(path: str = typer.Argument(..., help="New projects base fo
|
|
|
2873
2872
|
|
|
2874
2873
|
@settings.command("set-backend")
|
|
2875
2874
|
def settings_set_backend(
|
|
2876
|
-
url: str = typer.Argument(..., help="Backend base URL, e.g.
|
|
2875
|
+
url: str = typer.Argument(..., help=f"Backend base URL, e.g. {cfg.STANDARD_BACKEND_URL}")
|
|
2877
2876
|
):
|
|
2878
2877
|
"""
|
|
2879
2878
|
Set backend base URL used by CLI API calls.
|
|
@@ -2881,12 +2880,12 @@ def settings_set_backend(
|
|
|
2881
2880
|
Parameters
|
|
2882
2881
|
----------
|
|
2883
2882
|
url:
|
|
2884
|
-
Backend base URL
|
|
2883
|
+
Backend base URL.
|
|
2885
2884
|
|
|
2886
2885
|
Examples
|
|
2887
2886
|
--------
|
|
2888
2887
|
```bash
|
|
2889
|
-
mainsequence settings set-backend
|
|
2888
|
+
mainsequence settings set-backend <backend-url>
|
|
2890
2889
|
```
|
|
2891
2890
|
"""
|
|
2892
2891
|
out = cfg.set_backend_url(url)
|
|
@@ -2899,7 +2898,7 @@ def _settings_reset_impl() -> dict:
|
|
|
2899
2898
|
"""
|
|
2900
2899
|
Reset persistent CLI settings to standard defaults and clear session overrides.
|
|
2901
2900
|
"""
|
|
2902
|
-
standard_backend = cfg.normalize_backend_url(
|
|
2901
|
+
standard_backend = cfg.normalize_backend_url(cfg.STANDARD_BACKEND_URL)
|
|
2903
2902
|
standard_base = cfg.normalize_mainsequence_path(cfg.DEFAULTS.get("mainsequence_path"))
|
|
2904
2903
|
pathlib.Path(standard_base).mkdir(parents=True, exist_ok=True)
|
|
2905
2904
|
out = cfg.set_config(
|
|
@@ -2917,7 +2916,7 @@ def settings_reset():
|
|
|
2917
2916
|
"""
|
|
2918
2917
|
Reset CLI settings to standard defaults.
|
|
2919
2918
|
|
|
2920
|
-
Resets backend URL to
|
|
2919
|
+
Resets backend URL to the standard production backend, base folder to the
|
|
2921
2920
|
default `~/mainsequence`, and clears current terminal session overrides.
|
|
2922
2921
|
|
|
2923
2922
|
Examples
|
|
@@ -21,6 +21,8 @@ import subprocess
|
|
|
21
21
|
import sys
|
|
22
22
|
import time
|
|
23
23
|
|
|
24
|
+
from mainsequence.defaults import STANDARD_BACKEND_URL
|
|
25
|
+
|
|
24
26
|
APP_NAME = "MainSequenceCLI"
|
|
25
27
|
|
|
26
28
|
|
|
@@ -62,7 +64,7 @@ KEYCHAIN_SERVICE = "MainSequenceCLI.auth"
|
|
|
62
64
|
KEYCHAIN_ACCOUNT = "default"
|
|
63
65
|
|
|
64
66
|
DEFAULTS = {
|
|
65
|
-
"backend_url": os.environ.get("MAIN_SEQUENCE_BACKEND_URL", "
|
|
67
|
+
"backend_url": os.environ.get("MAIN_SEQUENCE_BACKEND_URL", f"{STANDARD_BACKEND_URL}/"),
|
|
66
68
|
"mainsequence_path": str(pathlib.Path.home() / "mainsequence"),
|
|
67
69
|
"version": 1,
|
|
68
70
|
}
|
|
@@ -212,7 +214,7 @@ def set_backend_url(url: str) -> dict:
|
|
|
212
214
|
Convenience helper to set backend_url in config.json.
|
|
213
215
|
|
|
214
216
|
Args:
|
|
215
|
-
url: Backend base URL
|
|
217
|
+
url: Backend base URL.
|
|
216
218
|
|
|
217
219
|
Returns:
|
|
218
220
|
dict: updated config
|
|
@@ -7,6 +7,8 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
import requests
|
|
9
9
|
|
|
10
|
+
from mainsequence.defaults import STANDARD_BACKEND_URL
|
|
11
|
+
|
|
10
12
|
from .exceptions import raise_for_response
|
|
11
13
|
from .utils import AuthLoaders, build_session
|
|
12
14
|
from .utils import loaders as _global_loaders
|
|
@@ -19,7 +21,7 @@ class MainSequenceClientConfig:
|
|
|
19
21
|
endpoint: str = (
|
|
20
22
|
os.getenv("MAINSEQUENCE_ENDPOINT")
|
|
21
23
|
or os.getenv("TDAG_ENDPOINT")
|
|
22
|
-
or
|
|
24
|
+
or STANDARD_BACKEND_URL
|
|
23
25
|
)
|
|
24
26
|
api_prefix: str = "/orm/api"
|
|
25
27
|
# (connect, read) — align with your utils DEFAULT_TIMEOUT behavior
|
{mainsequence-3.18.4 → mainsequence-3.18.6}/mainsequence/client/command_center/workspace_snapshot.py
RENAMED
|
@@ -7,6 +7,8 @@ from pathlib import Path
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
from urllib.parse import urlparse
|
|
9
9
|
|
|
10
|
+
from mainsequence.defaults import STANDARD_BACKEND_URL
|
|
11
|
+
|
|
10
12
|
from ..client import MainSequenceClientConfig
|
|
11
13
|
from ..utils import AuthLoaders
|
|
12
14
|
|
|
@@ -78,7 +80,7 @@ def _infer_command_center_url_from_endpoint(endpoint: str) -> str:
|
|
|
78
80
|
if host in {"localhost", "127.0.0.1"}:
|
|
79
81
|
return f"{scheme}://localhost:5173"
|
|
80
82
|
|
|
81
|
-
if host ==
|
|
83
|
+
if host == (urlparse(STANDARD_BACKEND_URL).hostname or ""):
|
|
82
84
|
return f"{scheme}://main-sequence.app"
|
|
83
85
|
|
|
84
86
|
if host.startswith("api."):
|
|
@@ -649,6 +649,13 @@ class SimpleTableUpdate(TableUpdateNode, BaseObjectOrm):
|
|
|
649
649
|
description="Simple table storage referenced by this update.",
|
|
650
650
|
)
|
|
651
651
|
tags: list[str] | None = Field(default=[], description="List of tags")
|
|
652
|
+
labels: list[str] = Field(
|
|
653
|
+
default_factory=list,
|
|
654
|
+
description=(
|
|
655
|
+
"Organizational labels attached to the simple table update. "
|
|
656
|
+
"These are helpers for grouping and discovery only and do not change runtime behavior or functionality."
|
|
657
|
+
),
|
|
658
|
+
)
|
|
652
659
|
description: str | None = Field(None, description="Optional HTML description")
|
|
653
660
|
update_details: SimpleTableUpdateDetails | int | None = None
|
|
654
661
|
run_configuration: SimpleTableRunConfiguration | None = None
|
|
@@ -275,6 +275,13 @@ class DataNodeUpdate(TableUpdateNode, BaseObjectOrm):
|
|
|
275
275
|
|
|
276
276
|
data_node_storage: int | DataNodeStorage
|
|
277
277
|
tags: list[str] | None = Field(default=[], description="List of tags")
|
|
278
|
+
labels: list[str] = Field(
|
|
279
|
+
default_factory=list,
|
|
280
|
+
description=(
|
|
281
|
+
"Organizational labels attached to the local time series update. "
|
|
282
|
+
"These are helpers for grouping and discovery only and do not change runtime behavior or functionality."
|
|
283
|
+
),
|
|
284
|
+
)
|
|
278
285
|
description: str | None = Field(None, description="Optional HTML description")
|
|
279
286
|
update_details: DataNodeUpdateDetails | int | None = None
|
|
280
287
|
run_configuration: RunConfiguration | None = None
|
|
@@ -8,6 +8,7 @@ from typing import Any, ClassVar, Literal
|
|
|
8
8
|
|
|
9
9
|
from pydantic import Field
|
|
10
10
|
|
|
11
|
+
from mainsequence.defaults import STANDARD_BACKEND_URL
|
|
11
12
|
from mainsequence.logconf import logger
|
|
12
13
|
|
|
13
14
|
from .base import (
|
|
@@ -141,7 +142,7 @@ class Organization(BasePydanticModel):
|
|
|
141
142
|
None,
|
|
142
143
|
title="Organization URL",
|
|
143
144
|
description="Optional public or internal URL for the organization.",
|
|
144
|
-
examples=[
|
|
145
|
+
examples=[STANDARD_BACKEND_URL],
|
|
145
146
|
)
|
|
146
147
|
organization_domain: str = Field(
|
|
147
148
|
...,
|
|
@@ -21,13 +21,14 @@ from requests.adapters import HTTPAdapter
|
|
|
21
21
|
from requests.structures import CaseInsensitiveDict
|
|
22
22
|
from urllib3.util.retry import Retry
|
|
23
23
|
|
|
24
|
+
from mainsequence.defaults import STANDARD_BACKEND_URL
|
|
24
25
|
from mainsequence.logconf import logger
|
|
25
26
|
|
|
26
27
|
# ---- Backend defaults (single source of truth) ----
|
|
27
28
|
TDAG_ENDPOINT = (
|
|
28
29
|
os.environ.get("TDAG_ENDPOINT")
|
|
29
30
|
or os.environ.get("MAINSEQUENCE_ENDPOINT")
|
|
30
|
-
or
|
|
31
|
+
or STANDARD_BACKEND_URL
|
|
31
32
|
)
|
|
32
33
|
API_ENDPOINT = f"{TDAG_ENDPOINT}/orm/api"
|
|
33
34
|
AUTH_ENDPOINT = TDAG_ENDPOINT.rstrip("/")
|
|
@@ -72,8 +73,8 @@ class AuthError(Exception):
|
|
|
72
73
|
def _jwt_reauth_hint() -> str:
|
|
73
74
|
return (
|
|
74
75
|
" Refresh your credentials with `mainsequence logout` and "
|
|
75
|
-
"`mainsequence login
|
|
76
|
-
"use `mainsequence login
|
|
76
|
+
"`mainsequence login`. If this code runs in a separate shell or IDE, "
|
|
77
|
+
"use `mainsequence login --export` and load the exported env vars there."
|
|
77
78
|
)
|
|
78
79
|
|
|
79
80
|
|
|
@@ -17,6 +17,7 @@ from structlog.contextvars import bind_contextvars, unbind_contextvars
|
|
|
17
17
|
from structlog.dev import ConsoleRenderer
|
|
18
18
|
from structlog.stdlib import BoundLogger
|
|
19
19
|
|
|
20
|
+
from .defaults import STANDARD_BACKEND_URL
|
|
20
21
|
from .instrumentation import OTelJSONRenderer
|
|
21
22
|
from .runtime_flags import is_running_in_pod
|
|
22
23
|
|
|
@@ -70,7 +71,7 @@ def _request_job_startup_state(*, timeout_s: float = 10.0) -> dict[str, Any]:
|
|
|
70
71
|
return (
|
|
71
72
|
os.getenv("TDAG_ENDPOINT")
|
|
72
73
|
or os.getenv("MAINSEQUENCE_ENDPOINT")
|
|
73
|
-
or
|
|
74
|
+
or STANDARD_BACKEND_URL
|
|
74
75
|
).rstrip("/")
|
|
75
76
|
|
|
76
77
|
def _auth_headers() -> tuple[CaseInsensitiveDict, bool]:
|
|
@@ -1540,6 +1540,46 @@ def test_settings_set_backend_json(cli_mod, runner, monkeypatch):
|
|
|
1540
1540
|
assert payload["backend_url"] == "https://example.test"
|
|
1541
1541
|
|
|
1542
1542
|
|
|
1543
|
+
def test_settings_reset(cli_mod, runner, monkeypatch):
|
|
1544
|
+
captured = {}
|
|
1545
|
+
monkeypatch.setattr(
|
|
1546
|
+
cli_mod.cfg,
|
|
1547
|
+
"DEFAULTS",
|
|
1548
|
+
{"backend_url": f"{cli_mod.cfg.STANDARD_BACKEND_URL}/", "mainsequence_path": "/tmp/mainsequence", "version": 1},
|
|
1549
|
+
)
|
|
1550
|
+
monkeypatch.setattr(
|
|
1551
|
+
cli_mod.cfg,
|
|
1552
|
+
"set_config",
|
|
1553
|
+
lambda updates: captured.update(updates) or updates | {"updated_at": "2026-04-20T00:00:00Z"},
|
|
1554
|
+
)
|
|
1555
|
+
monkeypatch.setattr(cli_mod.cfg, "clear_session_overrides", lambda: captured.update(cleared=True))
|
|
1556
|
+
|
|
1557
|
+
result = runner.invoke(cli_mod.app, ["settings", "reset"])
|
|
1558
|
+
assert result.exit_code == 0
|
|
1559
|
+
assert captured["backend_url"] == cli_mod.cfg.STANDARD_BACKEND_URL
|
|
1560
|
+
assert captured["mainsequence_path"].endswith("/tmp/mainsequence")
|
|
1561
|
+
assert captured["cleared"] is True
|
|
1562
|
+
assert "Settings reset to standard defaults" in result.output
|
|
1563
|
+
|
|
1564
|
+
|
|
1565
|
+
def test_settings_refresh_alias(cli_mod, runner, monkeypatch):
|
|
1566
|
+
monkeypatch.setattr(
|
|
1567
|
+
cli_mod.cfg,
|
|
1568
|
+
"DEFAULTS",
|
|
1569
|
+
{"backend_url": f"{cli_mod.cfg.STANDARD_BACKEND_URL}/", "mainsequence_path": "/tmp/mainsequence", "version": 1},
|
|
1570
|
+
)
|
|
1571
|
+
monkeypatch.setattr(
|
|
1572
|
+
cli_mod.cfg,
|
|
1573
|
+
"set_config",
|
|
1574
|
+
lambda updates: updates | {"updated_at": "2026-04-20T00:00:00Z"},
|
|
1575
|
+
)
|
|
1576
|
+
monkeypatch.setattr(cli_mod.cfg, "clear_session_overrides", lambda: None)
|
|
1577
|
+
|
|
1578
|
+
result = runner.invoke(cli_mod.app, ["settings", "refresh"])
|
|
1579
|
+
assert result.exit_code == 0
|
|
1580
|
+
assert "Settings reset to standard defaults" in result.output
|
|
1581
|
+
|
|
1582
|
+
|
|
1543
1583
|
def test_config_normalize_backend_url(cli_mod):
|
|
1544
1584
|
assert cli_mod.cfg.normalize_backend_url("127.0.0.1:800") == "http://127.0.0.1:800"
|
|
1545
1585
|
assert cli_mod.cfg.normalize_backend_url("localhost:8000") == "http://localhost:8000"
|
|
@@ -1582,7 +1622,7 @@ def test_config_session_overrides_do_not_persist(cli_mod, monkeypatch, tmp_path)
|
|
|
1582
1622
|
|
|
1583
1623
|
|
|
1584
1624
|
def test_login_mocked(cli_mod, runner, monkeypatch):
|
|
1585
|
-
|
|
1625
|
+
session_override = {}
|
|
1586
1626
|
monkeypatch.setattr(
|
|
1587
1627
|
cli_mod,
|
|
1588
1628
|
"login_via_browser",
|
|
@@ -1600,7 +1640,11 @@ def test_login_mocked(cli_mod, runner, monkeypatch):
|
|
|
1600
1640
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
1601
1641
|
)
|
|
1602
1642
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "secure OS storage")
|
|
1603
|
-
monkeypatch.setattr(
|
|
1643
|
+
monkeypatch.setattr(
|
|
1644
|
+
cli_mod.cfg,
|
|
1645
|
+
"set_session_overrides",
|
|
1646
|
+
lambda **kwargs: session_override.update(kwargs) or kwargs,
|
|
1647
|
+
)
|
|
1604
1648
|
monkeypatch.setattr(
|
|
1605
1649
|
cli_mod,
|
|
1606
1650
|
"get_projects",
|
|
@@ -1616,7 +1660,11 @@ def test_login_mocked(cli_mod, runner, monkeypatch):
|
|
|
1616
1660
|
assert "__ __" in result.output
|
|
1617
1661
|
assert "Signed in as user@example.com" in result.output
|
|
1618
1662
|
assert "Auth tokens are persisted in secure OS storage" in result.output
|
|
1619
|
-
assert
|
|
1663
|
+
assert cli_mod.cfg.STANDARD_BACKEND_URL in result.output
|
|
1664
|
+
assert session_override == {
|
|
1665
|
+
"backend_url": cli_mod.cfg.STANDARD_BACKEND_URL,
|
|
1666
|
+
"mainsequence_path": None,
|
|
1667
|
+
}
|
|
1620
1668
|
|
|
1621
1669
|
|
|
1622
1670
|
def test_login_with_backend_override(cli_mod, runner, monkeypatch):
|
|
@@ -1736,7 +1784,7 @@ def test_login_export_env(cli_mod, runner, monkeypatch):
|
|
|
1736
1784
|
"get_config",
|
|
1737
1785
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
1738
1786
|
)
|
|
1739
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
1787
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
1740
1788
|
monkeypatch.setattr(
|
|
1741
1789
|
cli_mod,
|
|
1742
1790
|
"get_projects",
|
|
@@ -1755,7 +1803,7 @@ def test_login_export_env(cli_mod, runner, monkeypatch):
|
|
|
1755
1803
|
|
|
1756
1804
|
def test_login_with_jwt_tokens(cli_mod, runner, monkeypatch):
|
|
1757
1805
|
saved = {}
|
|
1758
|
-
|
|
1806
|
+
session_override = {}
|
|
1759
1807
|
|
|
1760
1808
|
monkeypatch.setattr(
|
|
1761
1809
|
cli_mod.cfg,
|
|
@@ -1770,7 +1818,11 @@ def test_login_with_jwt_tokens(cli_mod, runner, monkeypatch):
|
|
|
1770
1818
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
1771
1819
|
)
|
|
1772
1820
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "local CLI auth storage")
|
|
1773
|
-
monkeypatch.setattr(
|
|
1821
|
+
monkeypatch.setattr(
|
|
1822
|
+
cli_mod.cfg,
|
|
1823
|
+
"set_session_overrides",
|
|
1824
|
+
lambda **kwargs: session_override.update(kwargs) or kwargs,
|
|
1825
|
+
)
|
|
1774
1826
|
monkeypatch.setattr(
|
|
1775
1827
|
cli_mod,
|
|
1776
1828
|
"get_projects",
|
|
@@ -1792,11 +1844,14 @@ def test_login_with_jwt_tokens(cli_mod, runner, monkeypatch):
|
|
|
1792
1844
|
assert saved == {"username": "", "access": "acc-123", "refresh": "ref-456"}
|
|
1793
1845
|
assert "Signed in with JWT tokens" in result.output
|
|
1794
1846
|
assert "Auth tokens are persisted in local CLI auth storage" in result.output
|
|
1795
|
-
assert
|
|
1847
|
+
assert session_override == {
|
|
1848
|
+
"backend_url": cli_mod.cfg.STANDARD_BACKEND_URL,
|
|
1849
|
+
"mainsequence_path": None,
|
|
1850
|
+
}
|
|
1796
1851
|
|
|
1797
1852
|
|
|
1798
1853
|
def test_login_runtime_credential_exchanges_token(cli_mod, runner, monkeypatch):
|
|
1799
|
-
|
|
1854
|
+
session_override = {}
|
|
1800
1855
|
exchange = {"called": False}
|
|
1801
1856
|
saved = {}
|
|
1802
1857
|
|
|
@@ -1825,7 +1880,11 @@ def test_login_runtime_credential_exchanges_token(cli_mod, runner, monkeypatch):
|
|
|
1825
1880
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
1826
1881
|
)
|
|
1827
1882
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "local CLI auth storage")
|
|
1828
|
-
monkeypatch.setattr(
|
|
1883
|
+
monkeypatch.setattr(
|
|
1884
|
+
cli_mod.cfg,
|
|
1885
|
+
"set_session_overrides",
|
|
1886
|
+
lambda **kwargs: session_override.update(kwargs) or kwargs,
|
|
1887
|
+
)
|
|
1829
1888
|
|
|
1830
1889
|
result = runner.invoke(cli_mod.app, ["login"])
|
|
1831
1890
|
|
|
@@ -1837,7 +1896,10 @@ def test_login_runtime_credential_exchanges_token(cli_mod, runner, monkeypatch):
|
|
|
1837
1896
|
assert "Signed in with runtime credential" in result.output
|
|
1838
1897
|
assert "no CLI JWT refresh token exists" in result.output
|
|
1839
1898
|
assert "re-exchange the runtime credential automatically" in result.output
|
|
1840
|
-
assert
|
|
1899
|
+
assert session_override == {
|
|
1900
|
+
"backend_url": cli_mod.cfg.STANDARD_BACKEND_URL,
|
|
1901
|
+
"mainsequence_path": None,
|
|
1902
|
+
}
|
|
1841
1903
|
|
|
1842
1904
|
|
|
1843
1905
|
def test_login_runtime_credential_export(monkeypatch, cli_mod, runner):
|
|
@@ -1852,7 +1914,7 @@ def test_login_runtime_credential_export(monkeypatch, cli_mod, runner):
|
|
|
1852
1914
|
"get_config",
|
|
1853
1915
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
1854
1916
|
)
|
|
1855
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
1917
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
1856
1918
|
|
|
1857
1919
|
result = runner.invoke(cli_mod.app, ["login", "--export"])
|
|
1858
1920
|
|
|
@@ -2040,7 +2102,7 @@ def test_login_export_env_with_jwt_tokens_omits_username(cli_mod, runner, monkey
|
|
|
2040
2102
|
"get_config",
|
|
2041
2103
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
2042
2104
|
)
|
|
2043
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
2105
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
2044
2106
|
|
|
2045
2107
|
result = runner.invoke(
|
|
2046
2108
|
cli_mod.app,
|
|
@@ -2078,7 +2140,7 @@ def test_login_warns_when_secure_persist_fails(cli_mod, runner, monkeypatch):
|
|
|
2078
2140
|
)
|
|
2079
2141
|
monkeypatch.setattr(cli_mod.cfg, "save_tokens", lambda username, access, refresh: False)
|
|
2080
2142
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "secure OS storage")
|
|
2081
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
2143
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
2082
2144
|
monkeypatch.setattr(
|
|
2083
2145
|
cli_mod,
|
|
2084
2146
|
"get_projects",
|
|
@@ -2111,7 +2173,7 @@ def test_login_does_not_fetch_projects_after_success(cli_mod, runner, monkeypatc
|
|
|
2111
2173
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
2112
2174
|
)
|
|
2113
2175
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "local CLI auth storage")
|
|
2114
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
2176
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
2115
2177
|
monkeypatch.setattr(
|
|
2116
2178
|
cli_mod,
|
|
2117
2179
|
"get_projects",
|
|
@@ -2135,7 +2197,7 @@ def test_jwt_login_does_not_fetch_projects_after_success(cli_mod, runner, monkey
|
|
|
2135
2197
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
2136
2198
|
)
|
|
2137
2199
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "local CLI auth storage")
|
|
2138
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
2200
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
2139
2201
|
monkeypatch.setattr(
|
|
2140
2202
|
cli_mod,
|
|
2141
2203
|
"get_projects",
|
|
@@ -2193,7 +2255,7 @@ def test_login_no_open_prints_authorize_url(cli_mod, runner, monkeypatch):
|
|
|
2193
2255
|
lambda: {"mainsequence_path": "/tmp/mainsequence"},
|
|
2194
2256
|
)
|
|
2195
2257
|
monkeypatch.setattr(cli_mod.cfg, "auth_persistence_label", lambda: "local CLI auth storage")
|
|
2196
|
-
monkeypatch.setattr(cli_mod.cfg, "
|
|
2258
|
+
monkeypatch.setattr(cli_mod.cfg, "set_session_overrides", lambda **kwargs: kwargs)
|
|
2197
2259
|
monkeypatch.setattr(cli_mod.cfg, "save_tokens", lambda username, access, refresh: True)
|
|
2198
2260
|
monkeypatch.setattr(cli_mod, "get_current_user_profile", lambda: {"username": "user@example.com"})
|
|
2199
2261
|
|
|
@@ -7,8 +7,14 @@ import pandas as pd
|
|
|
7
7
|
import pytest
|
|
8
8
|
from pydantic import ValidationError
|
|
9
9
|
|
|
10
|
-
from mainsequence.client.
|
|
11
|
-
from mainsequence.client.
|
|
10
|
+
from mainsequence.client.command_center import Workspace
|
|
11
|
+
from mainsequence.client.models_simple_tables import SimpleTableStorage, SimpleTableUpdate
|
|
12
|
+
from mainsequence.client.models_tdag import (
|
|
13
|
+
DataNodeStorage,
|
|
14
|
+
DataNodeUpdate,
|
|
15
|
+
DataNodeUpdateDetails,
|
|
16
|
+
Project,
|
|
17
|
+
)
|
|
12
18
|
from mainsequence.tdag import DataNode
|
|
13
19
|
from mainsequence.tdag.data_nodes.models import RecordDefinition
|
|
14
20
|
from mainsequence.tdag.data_nodes.run_operations import UpdateRunner
|
|
@@ -55,6 +61,18 @@ def test_data_node_storage_accepts_namespace():
|
|
|
55
61
|
assert storage.namespace == "pytest_case_123"
|
|
56
62
|
|
|
57
63
|
|
|
64
|
+
def test_data_node_update_accepts_labels():
|
|
65
|
+
update = DataNodeUpdate(
|
|
66
|
+
id=44,
|
|
67
|
+
update_hash="issue-44-update-hash",
|
|
68
|
+
data_node_storage=1,
|
|
69
|
+
build_configuration={},
|
|
70
|
+
labels=["pricing", "daily"],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
assert update.labels == ["pricing", "daily"]
|
|
74
|
+
|
|
75
|
+
|
|
58
76
|
def test_simple_table_storage_accepts_namespace():
|
|
59
77
|
storage = SimpleTableStorage(
|
|
60
78
|
id=15,
|
|
@@ -68,6 +86,57 @@ def test_simple_table_storage_accepts_namespace():
|
|
|
68
86
|
assert storage.namespace == "pytest_case_456"
|
|
69
87
|
|
|
70
88
|
|
|
89
|
+
def test_simple_table_update_accepts_labels():
|
|
90
|
+
update = SimpleTableUpdate(
|
|
91
|
+
id=44,
|
|
92
|
+
update_hash="simple-table-update-hash",
|
|
93
|
+
remote_table=1,
|
|
94
|
+
build_configuration={},
|
|
95
|
+
labels=["reference", "daily"],
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
assert update.labels == ["reference", "daily"]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_label_fields_exist_on_workspace_project_and_storage_models():
|
|
102
|
+
workspace = Workspace(
|
|
103
|
+
id=1,
|
|
104
|
+
title="Workspace",
|
|
105
|
+
schemaVersion=1,
|
|
106
|
+
layoutKind="custom",
|
|
107
|
+
createdAt="2026-04-20T00:00:00Z",
|
|
108
|
+
updatedAt="2026-04-20T00:00:00Z",
|
|
109
|
+
labels=["desk"],
|
|
110
|
+
)
|
|
111
|
+
project = Project(
|
|
112
|
+
id=1,
|
|
113
|
+
project_name="Project",
|
|
114
|
+
is_initialized=True,
|
|
115
|
+
labels=["research"],
|
|
116
|
+
)
|
|
117
|
+
data_node_storage = DataNodeStorage(
|
|
118
|
+
id=12,
|
|
119
|
+
storage_hash="prices_storage_hash",
|
|
120
|
+
data_source=1,
|
|
121
|
+
source_class_name="PricesNode",
|
|
122
|
+
creation_date="2026-04-13T00:00:00Z",
|
|
123
|
+
labels=["market-data"],
|
|
124
|
+
)
|
|
125
|
+
simple_table_storage = SimpleTableStorage(
|
|
126
|
+
id=15,
|
|
127
|
+
storage_hash="orders_storage_hash",
|
|
128
|
+
data_source={"id": 1},
|
|
129
|
+
schema={"model": "tests.OrderRow", "fields": []},
|
|
130
|
+
source_class_name="OrderUpdater",
|
|
131
|
+
labels=["reference-data"],
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
assert workspace.labels == ["desk"]
|
|
135
|
+
assert project.labels == ["research"]
|
|
136
|
+
assert data_node_storage.labels == ["market-data"]
|
|
137
|
+
assert simple_table_storage.labels == ["reference-data"]
|
|
138
|
+
|
|
139
|
+
|
|
71
140
|
def test_record_definition_rejects_column_names_longer_than_63_characters():
|
|
72
141
|
with pytest.raises(ValidationError, match="at most 63 characters"):
|
|
73
142
|
RecordDefinition(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/dashboards/streamlit/SKILL.md
RENAMED
|
File without changes
|
{mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/data_access/exploration/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md
RENAMED
|
File without changes
|
{mainsequence-3.18.4 → mainsequence-3.18.6}/agent_scaffold/skills/maintenance/local_journal/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|