mainsequence 8.1.18__tar.gz → 8.1.20.dev1__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-8.1.18/mainsequence.egg-info → mainsequence-8.1.20.dev1}/PKG-INFO +1 -1
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md +7 -5
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/api.py +2 -6
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/cli.py +0 -16
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/agent_runtime_models.py +16 -16
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1/mainsequence.egg-info}/PKG-INFO +1 -1
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/SOURCES.txt +1 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/pyproject.toml +18 -1
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli.py +6 -26
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_client.py +5 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_batch_jobs_from_file.py +26 -0
- mainsequence-8.1.20.dev1/tests/test_dev_release_version.py +118 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_filter_normalization.py +82 -7
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_tables_client_models.py +45 -1
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_configuration_client.py +43 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/LICENSE +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/MANIFEST.in +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/README.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/AGENTS.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/data_publishing/time_index_table_updates/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/maintenance/code_repository_maintenance/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/sdk_code_repository_execution/SKILL.md +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/__main__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/bootstrap.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/browser_auth.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/code_repository_status.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/config.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/docker_utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/doctor.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/local_ops.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/migrations.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/model_filters.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/pydantic_cli.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/sdk_utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/ssh_utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/cli/ui.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/base.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/client.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/compute_validation.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/dtype_codec.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/exceptions.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/github_issues.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/metatables/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/metatables/core.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_foundry.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_helpers.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/models_user.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/observability.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/code_repository_context.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/code_repository_skills.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/defaults.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/instrumentation/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/instrumentation/utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/logconf.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/__main__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/future_registry.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/hashing.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/alembic.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/env.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/provider.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/registry.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/schema_names.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_refs.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/__init__.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/configuration.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/dependencies.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/managers.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/namespacing.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/runner.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/updaters.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/meta_tables/time_index_table_updates/utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/repository_identity_security.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/runtime_flags.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/scaffold_skills.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/dependency_links.txt +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/entry_points.txt +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/requires.txt +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence.egg-info/top_level.txt +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/setup.cfg +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/fixtures/time_index_table_update_hash_v2_golden.json +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_auth_precedence.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_canonical_api_route_contract.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli_browser_auth.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_cli_migrations.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_branch_contract.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_documentation_contract.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_runtime_context.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_skills.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_dependency_extras.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_duckdb_interface_dimensions.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_environment_resource_context.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_environment_response_contracts.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_github_issues_client.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_instrumentation.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_local_ops.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_logconf.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_table_migrations.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_models_user_request_bound_auth.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_notification_uid_contract.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_observability_client.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_pod_project_resolution.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_scaffold_skills.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_schema_names.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_secret_client_model.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_source_table_configuration.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_sqlite_interface_dimensions.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_ssh_utils.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_access_dimension_audit.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_dimension_queries.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_configuration.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_flow.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_time_index_table_update_hard_cut.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_runner_uid_runtime.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_statistics.py +0 -0
- {mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_update_uid_guards.py +0 -0
{mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/agent_scaffold/skills/a2a_sdk_execution/SKILL.md
RENAMED
|
@@ -43,14 +43,16 @@ internally and sends a standard A2A message.
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
mainsequence agent search "<discoveryPrompt>" \
|
|
46
|
-
--environment-uid "<organizationEnvironmentUid>" \
|
|
47
46
|
--limit 10 \
|
|
48
47
|
--json
|
|
49
48
|
```
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
The SDK resolves the active Git branch once for the process and scopes discovery
|
|
51
|
+
to its Organization Environment. Do not supply a branch or Environment UID.
|
|
52
|
+
An unregistered branch fails only when discovery is attempted.
|
|
53
|
+
For an exact Python lookup, use `Agent.filter(name="SentinelExecutor")` and
|
|
54
|
+
inspect the returned Agent UID and `code_repository_branch_uid`; names are not
|
|
55
|
+
unique routing authority.
|
|
54
56
|
|
|
55
57
|
4. Treat the CLI output as authoritative.
|
|
56
58
|
5. Prefer the highest `combined_score` when present.
|
|
@@ -321,7 +323,7 @@ handle for a different task or conversation.
|
|
|
321
323
|
## Deterministic Execution Path
|
|
322
324
|
|
|
323
325
|
1. Build the discovery prompt.
|
|
324
|
-
2. Run `mainsequence agent search "<discoveryPrompt>" --
|
|
326
|
+
2. Run `mainsequence agent search "<discoveryPrompt>" --limit <n> --json`.
|
|
325
327
|
3. Select the target agent.
|
|
326
328
|
4. Create or resolve the target session with `mainsequence agent session get_or_create`.
|
|
327
329
|
5. Use the returned session `uid`.
|
|
@@ -1161,16 +1161,14 @@ def delete_organization_team(
|
|
|
1161
1161
|
|
|
1162
1162
|
def list_agents(
|
|
1163
1163
|
*,
|
|
1164
|
-
organization_environment_uid: str,
|
|
1165
1164
|
timeout: int | None = None,
|
|
1166
1165
|
filters: dict[str, Any] | None = None,
|
|
1167
1166
|
) -> list[dict[str, Any]]:
|
|
1168
1167
|
"""
|
|
1169
|
-
List agents in
|
|
1168
|
+
List agents in the Git-resolved Organization Environment via the SDK client model.
|
|
1170
1169
|
"""
|
|
1171
1170
|
try:
|
|
1172
1171
|
read_params = dict(filters or {})
|
|
1173
|
-
read_params["organization_environment_uid"] = organization_environment_uid
|
|
1174
1172
|
payload = _run_sdk_model_operation(
|
|
1175
1173
|
module_name="mainsequence.client.agent_runtime_models",
|
|
1176
1174
|
class_name="Agent",
|
|
@@ -1293,12 +1291,11 @@ def get_agent_resource_usage(
|
|
|
1293
1291
|
def semantic_search_agents(
|
|
1294
1292
|
q: str,
|
|
1295
1293
|
*,
|
|
1296
|
-
organization_environment_uid: str,
|
|
1297
1294
|
limit: int = 20,
|
|
1298
1295
|
timeout: int | None = None,
|
|
1299
1296
|
) -> list[dict[str, Any]]:
|
|
1300
1297
|
"""
|
|
1301
|
-
Search agents in
|
|
1298
|
+
Search agents in the Git-resolved Organization Environment.
|
|
1302
1299
|
"""
|
|
1303
1300
|
try:
|
|
1304
1301
|
payload = _run_sdk_model_operation(
|
|
@@ -1306,7 +1303,6 @@ def semantic_search_agents(
|
|
|
1306
1303
|
class_name="Agent",
|
|
1307
1304
|
operation=lambda ClientAgent: ClientAgent.semantic_search(
|
|
1308
1305
|
q,
|
|
1309
|
-
organization_environment_uid=organization_environment_uid,
|
|
1310
1306
|
limit=limit,
|
|
1311
1307
|
timeout=timeout,
|
|
1312
1308
|
),
|
|
@@ -3541,7 +3541,6 @@ def _render_owner_resource_usage(payload: dict[str, object], *, title: str) -> N
|
|
|
3541
3541
|
|
|
3542
3542
|
|
|
3543
3543
|
def _agent_list_impl(
|
|
3544
|
-
organization_environment_uid: str,
|
|
3545
3544
|
timeout: int | None,
|
|
3546
3545
|
filter_entries: list[str] | None,
|
|
3547
3546
|
show_filters: bool,
|
|
@@ -3556,7 +3555,6 @@ def _agent_list_impl(
|
|
|
3556
3555
|
|
|
3557
3556
|
try:
|
|
3558
3557
|
agents = list_agents(
|
|
3559
|
-
organization_environment_uid=organization_environment_uid,
|
|
3560
3558
|
timeout=timeout,
|
|
3561
3559
|
filters=filters,
|
|
3562
3560
|
)
|
|
@@ -3630,7 +3628,6 @@ def _agent_detail_impl(
|
|
|
3630
3628
|
def _agent_search_impl(
|
|
3631
3629
|
*,
|
|
3632
3630
|
q: str,
|
|
3633
|
-
organization_environment_uid: str,
|
|
3634
3631
|
limit: int,
|
|
3635
3632
|
timeout: int | None,
|
|
3636
3633
|
) -> None:
|
|
@@ -3639,7 +3636,6 @@ def _agent_search_impl(
|
|
|
3639
3636
|
try:
|
|
3640
3637
|
results = semantic_search_agents(
|
|
3641
3638
|
q,
|
|
3642
|
-
organization_environment_uid=organization_environment_uid,
|
|
3643
3639
|
limit=limit,
|
|
3644
3640
|
timeout=timeout,
|
|
3645
3641
|
)
|
|
@@ -4697,11 +4693,6 @@ def _print_time_index_table_search_section(
|
|
|
4697
4693
|
|
|
4698
4694
|
@agent.command("list")
|
|
4699
4695
|
def agent_list_cmd(
|
|
4700
|
-
organization_environment_uid: uuid.UUID = typer.Option(
|
|
4701
|
-
...,
|
|
4702
|
-
"--environment-uid",
|
|
4703
|
-
help="Organization Environment UID that scopes Agent discovery.",
|
|
4704
|
-
),
|
|
4705
4696
|
filter_entries: list[str] | None = typer.Option(None, "--filter", help=LIST_FILTER_OPTION_HELP),
|
|
4706
4697
|
show_filters: bool = typer.Option(
|
|
4707
4698
|
False, "--show-filters", help="Show the filters supported by this list command and exit."
|
|
@@ -4712,7 +4703,6 @@ def agent_list_cmd(
|
|
|
4712
4703
|
List agents visible to the authenticated user.
|
|
4713
4704
|
"""
|
|
4714
4705
|
_agent_list_impl(
|
|
4715
|
-
organization_environment_uid=str(organization_environment_uid),
|
|
4716
4706
|
timeout=timeout,
|
|
4717
4707
|
filter_entries=filter_entries,
|
|
4718
4708
|
show_filters=show_filters,
|
|
@@ -4799,11 +4789,6 @@ def agent_resource_usage_cmd(
|
|
|
4799
4789
|
@agent.command("search")
|
|
4800
4790
|
def agent_search_cmd(
|
|
4801
4791
|
q: str = typer.Argument(..., help="Natural-language query to match against agents."),
|
|
4802
|
-
organization_environment_uid: uuid.UUID = typer.Option(
|
|
4803
|
-
...,
|
|
4804
|
-
"--environment-uid",
|
|
4805
|
-
help="Organization Environment UID that scopes Agent discovery.",
|
|
4806
|
-
),
|
|
4807
4792
|
limit: int = typer.Option(
|
|
4808
4793
|
20, "--limit", min=1, max=100, help="Maximum number of ranked agent matches to return."
|
|
4809
4794
|
),
|
|
@@ -4823,7 +4808,6 @@ def agent_search_cmd(
|
|
|
4823
4808
|
"""
|
|
4824
4809
|
_agent_search_impl(
|
|
4825
4810
|
q=q,
|
|
4826
|
-
organization_environment_uid=str(organization_environment_uid),
|
|
4827
4811
|
limit=limit,
|
|
4828
4812
|
timeout=timeout,
|
|
4829
4813
|
)
|
{mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/mainsequence/client/agent_runtime_models.py
RENAMED
|
@@ -12,7 +12,12 @@ from typing import Any, ClassVar, Literal
|
|
|
12
12
|
import requests
|
|
13
13
|
from pydantic import ConfigDict, Field, model_validator
|
|
14
14
|
|
|
15
|
-
from .base import
|
|
15
|
+
from .base import (
|
|
16
|
+
BaseObjectOrm,
|
|
17
|
+
BasePydanticModel,
|
|
18
|
+
CurrentCodeRepositoryEnvironmentResourceMixin,
|
|
19
|
+
ShareableObjectMixin,
|
|
20
|
+
)
|
|
16
21
|
from .exceptions import ApiError, raise_for_response
|
|
17
22
|
from .observability import (
|
|
18
23
|
EnvironmentLogSearchMixin,
|
|
@@ -465,6 +470,7 @@ def _runtime_access_retry_seconds(access: AgentSessionRuntimeAccess) -> float:
|
|
|
465
470
|
|
|
466
471
|
|
|
467
472
|
class Agent(
|
|
473
|
+
CurrentCodeRepositoryEnvironmentResourceMixin,
|
|
468
474
|
EnvironmentLogSearchMixin,
|
|
469
475
|
OwnerLogMixin,
|
|
470
476
|
OwnerResourceUsageMixin,
|
|
@@ -482,14 +488,22 @@ class Agent(
|
|
|
482
488
|
|
|
483
489
|
FILTERSET_FIELDS: ClassVar[dict[str, list[str]] | None] = {
|
|
484
490
|
"uid": ["exact", "in"],
|
|
491
|
+
"name": ["exact"],
|
|
485
492
|
"search": ["exact"],
|
|
486
493
|
}
|
|
487
494
|
FILTER_VALUE_NORMALIZERS: ClassVar[dict[str, str]] = {
|
|
488
495
|
"uid": "uid",
|
|
489
496
|
"uid__in": "uid",
|
|
497
|
+
"name": "str",
|
|
490
498
|
"search": "str",
|
|
491
499
|
}
|
|
492
500
|
|
|
501
|
+
@classmethod
|
|
502
|
+
def _sdk_owned_query_context(cls, operation: str) -> dict[str, str]:
|
|
503
|
+
if operation in {f"{cls.__name__}.filter", f"{cls.__name__}.semantic_search"}:
|
|
504
|
+
return super()._sdk_owned_query_context(operation)
|
|
505
|
+
return {}
|
|
506
|
+
|
|
493
507
|
@classmethod
|
|
494
508
|
def search_logs(
|
|
495
509
|
cls,
|
|
@@ -522,16 +536,6 @@ class Agent(
|
|
|
522
536
|
timeout=timeout,
|
|
523
537
|
)
|
|
524
538
|
|
|
525
|
-
READ_QUERY_PARAMS: ClassVar[dict[str, str]] = {
|
|
526
|
-
"organization_environment_uid": "uid",
|
|
527
|
-
}
|
|
528
|
-
READ_QUERY_PARAM_DESCRIPTIONS: ClassVar[dict[str, str]] = {
|
|
529
|
-
"organization_environment_uid": (
|
|
530
|
-
"Required Organization Environment boundary for Agent discovery. "
|
|
531
|
-
"This scopes reads and does not assign an environment to an Agent."
|
|
532
|
-
),
|
|
533
|
-
}
|
|
534
|
-
|
|
535
539
|
uid: str | None = Field(None, description="Public UID of the agent resource.")
|
|
536
540
|
name: str = Field(
|
|
537
541
|
..., description="Human-readable display name for the agent inside the organization."
|
|
@@ -667,7 +671,6 @@ class Agent(
|
|
|
667
671
|
cls,
|
|
668
672
|
q: str,
|
|
669
673
|
*,
|
|
670
|
-
organization_environment_uid: str,
|
|
671
674
|
limit: int = 20,
|
|
672
675
|
timeout=None,
|
|
673
676
|
) -> list[AgentSemanticSearchResult]:
|
|
@@ -688,12 +691,9 @@ class Agent(
|
|
|
688
691
|
raise ValueError("limit must be between 1 and 100")
|
|
689
692
|
|
|
690
693
|
body: dict[str, Any] = {
|
|
691
|
-
"organization_environment_uid": cls._coerce_filter_uid(
|
|
692
|
-
organization_environment_uid,
|
|
693
|
-
field_name="organization_environment_uid",
|
|
694
|
-
),
|
|
695
694
|
"q": q,
|
|
696
695
|
"limit": limit,
|
|
696
|
+
**cls._sdk_owned_query_context(f"{cls.__name__}.semantic_search"),
|
|
697
697
|
}
|
|
698
698
|
|
|
699
699
|
payload = {"json": serialize_to_json(body)}
|
|
@@ -105,6 +105,7 @@ tests/test_code_repository_documentation_contract.py
|
|
|
105
105
|
tests/test_code_repository_runtime_context.py
|
|
106
106
|
tests/test_code_repository_skills.py
|
|
107
107
|
tests/test_dependency_extras.py
|
|
108
|
+
tests/test_dev_release_version.py
|
|
108
109
|
tests/test_duckdb_interface_dimensions.py
|
|
109
110
|
tests/test_environment_resource_context.py
|
|
110
111
|
tests/test_environment_response_contracts.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mainsequence"
|
|
7
|
-
version = "8.1.
|
|
7
|
+
version = "8.1.20.dev1"
|
|
8
8
|
description = "Main Sequence SDK "
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -95,6 +95,23 @@ publish-url = "https://test.pypi.org/legacy/"
|
|
|
95
95
|
explicit = true
|
|
96
96
|
|
|
97
97
|
|
|
98
|
+
# --------------------
|
|
99
|
+
# Testing (pytest)
|
|
100
|
+
# --------------------
|
|
101
|
+
[tool.pytest.ini_options]
|
|
102
|
+
testpaths = ["tests"]
|
|
103
|
+
# Put the repository root on sys.path so tests can import `scripts`. `pytest`
|
|
104
|
+
# invoked as `python -m pytest` gets this from the CWD, but the `pytest`
|
|
105
|
+
# entrypoint (what `uv run pytest` and CI use) does not.
|
|
106
|
+
pythonpath = ["."]
|
|
107
|
+
# `live` tests talk to a real backend and need credentials, so they are
|
|
108
|
+
# deselected by default. CI and a plain `pytest` therefore run offline.
|
|
109
|
+
# Run them explicitly with `pytest -m live`.
|
|
110
|
+
addopts = "-m 'not live'"
|
|
111
|
+
markers = [
|
|
112
|
+
"live: talks to a live Main Sequence backend and needs credentials; deselected unless `-m live` is passed",
|
|
113
|
+
]
|
|
114
|
+
|
|
98
115
|
# --------------------
|
|
99
116
|
# Formatting (Black)
|
|
100
117
|
# --------------------
|
|
@@ -579,7 +579,6 @@ def test_list_organization_teams_uses_client_model(cli_mod, monkeypatch):
|
|
|
579
579
|
def test_list_agents_uses_client_model(cli_mod, monkeypatch):
|
|
580
580
|
api_mod = importlib.import_module("mainsequence.cli.api")
|
|
581
581
|
captured = {}
|
|
582
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
583
582
|
|
|
584
583
|
class FakeAgent:
|
|
585
584
|
def __init__(self, uid, name):
|
|
@@ -607,7 +606,6 @@ def test_list_agents_uses_client_model(cli_mod, monkeypatch):
|
|
|
607
606
|
monkeypatch.setattr(api_mod, "_run_sdk_model_operation", _run_sdk_model_operation)
|
|
608
607
|
|
|
609
608
|
out = api_mod.list_agents(
|
|
610
|
-
organization_environment_uid=environment_uid,
|
|
611
609
|
timeout=9,
|
|
612
610
|
filters={"search": "Research"},
|
|
613
611
|
)
|
|
@@ -615,10 +613,7 @@ def test_list_agents_uses_client_model(cli_mod, monkeypatch):
|
|
|
615
613
|
"module_name": "mainsequence.client.agent_runtime_models",
|
|
616
614
|
"class_name": "Agent",
|
|
617
615
|
"timeout": 9,
|
|
618
|
-
"filters": {
|
|
619
|
-
"search": "Research",
|
|
620
|
-
"organization_environment_uid": environment_uid,
|
|
621
|
-
},
|
|
616
|
+
"filters": {"search": "Research"},
|
|
622
617
|
}
|
|
623
618
|
assert out == [
|
|
624
619
|
{
|
|
@@ -677,7 +672,6 @@ def test_get_code_repository_repository_uses_public_client_model(cli_mod, monkey
|
|
|
677
672
|
def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
|
|
678
673
|
api_mod = importlib.import_module("mainsequence.cli.api")
|
|
679
674
|
captured = {}
|
|
680
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
681
675
|
|
|
682
676
|
class FakeSearchResult:
|
|
683
677
|
def __init__(self):
|
|
@@ -710,12 +704,10 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
|
|
|
710
704
|
cls,
|
|
711
705
|
q,
|
|
712
706
|
*,
|
|
713
|
-
organization_environment_uid,
|
|
714
707
|
limit=20,
|
|
715
708
|
timeout=None,
|
|
716
709
|
):
|
|
717
710
|
captured["q"] = q
|
|
718
|
-
captured["organization_environment_uid"] = organization_environment_uid
|
|
719
711
|
captured["limit"] = limit
|
|
720
712
|
captured["timeout"] = timeout
|
|
721
713
|
return [FakeSearchResult()]
|
|
@@ -726,7 +718,6 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
|
|
|
726
718
|
|
|
727
719
|
out = api_mod.semantic_search_agents(
|
|
728
720
|
"data research",
|
|
729
|
-
organization_environment_uid=environment_uid,
|
|
730
721
|
limit=10,
|
|
731
722
|
timeout=17,
|
|
732
723
|
)
|
|
@@ -734,7 +725,6 @@ def test_semantic_search_agents_uses_client_model(cli_mod, monkeypatch):
|
|
|
734
725
|
"module_name": "mainsequence.client.agent_runtime_models",
|
|
735
726
|
"class_name": "Agent",
|
|
736
727
|
"q": "data research",
|
|
737
|
-
"organization_environment_uid": environment_uid,
|
|
738
728
|
"limit": 10,
|
|
739
729
|
"timeout": 17,
|
|
740
730
|
}
|
|
@@ -6322,12 +6312,11 @@ def test_code_repository_code_repository_resource_delete_fastapi_requires_confir
|
|
|
6322
6312
|
|
|
6323
6313
|
|
|
6324
6314
|
def test_agent_list(cli_mod, runner, monkeypatch):
|
|
6325
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
6326
6315
|
monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
|
|
6327
6316
|
monkeypatch.setattr(
|
|
6328
6317
|
cli_mod,
|
|
6329
6318
|
"list_agents",
|
|
6330
|
-
lambda
|
|
6319
|
+
lambda timeout=None, filters=None: [
|
|
6331
6320
|
{
|
|
6332
6321
|
"uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
|
|
6333
6322
|
"name": "Research Copilot",
|
|
@@ -6343,7 +6332,7 @@ def test_agent_list(cli_mod, runner, monkeypatch):
|
|
|
6343
6332
|
|
|
6344
6333
|
result = runner.invoke(
|
|
6345
6334
|
cli_mod.app,
|
|
6346
|
-
["agent", "list", "--
|
|
6335
|
+
["agent", "list", "--filter", "name=SentinelExecutor"],
|
|
6347
6336
|
)
|
|
6348
6337
|
assert result.exit_code == 0
|
|
6349
6338
|
assert "Agents" in result.output
|
|
@@ -6355,12 +6344,11 @@ def test_agent_list(cli_mod, runner, monkeypatch):
|
|
|
6355
6344
|
|
|
6356
6345
|
|
|
6357
6346
|
def test_agent_list_json(cli_mod, runner, monkeypatch):
|
|
6358
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
6359
6347
|
monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
|
|
6360
6348
|
monkeypatch.setattr(
|
|
6361
6349
|
cli_mod,
|
|
6362
6350
|
"list_agents",
|
|
6363
|
-
lambda
|
|
6351
|
+
lambda timeout=None, filters=None: [
|
|
6364
6352
|
{
|
|
6365
6353
|
"uid": "e0e75693-4110-464c-93e0-82c7fd9c9a23",
|
|
6366
6354
|
"name": "Research Copilot",
|
|
@@ -6376,7 +6364,7 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
|
|
|
6376
6364
|
|
|
6377
6365
|
result = runner.invoke(
|
|
6378
6366
|
cli_mod.app,
|
|
6379
|
-
["agent", "list", "--
|
|
6367
|
+
["agent", "list", "--json"],
|
|
6380
6368
|
)
|
|
6381
6369
|
assert result.exit_code == 0
|
|
6382
6370
|
payload = json.loads(result.output)
|
|
@@ -6386,14 +6374,12 @@ def test_agent_list_json(cli_mod, runner, monkeypatch):
|
|
|
6386
6374
|
|
|
6387
6375
|
def test_agent_search(cli_mod, runner, monkeypatch):
|
|
6388
6376
|
captured = {}
|
|
6389
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
6390
6377
|
monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
|
|
6391
6378
|
|
|
6392
|
-
def _search(q, *,
|
|
6379
|
+
def _search(q, *, limit=20, timeout=None):
|
|
6393
6380
|
captured.update(
|
|
6394
6381
|
{
|
|
6395
6382
|
"q": q,
|
|
6396
|
-
"organization_environment_uid": organization_environment_uid,
|
|
6397
6383
|
"limit": limit,
|
|
6398
6384
|
"timeout": timeout,
|
|
6399
6385
|
}
|
|
@@ -6417,8 +6403,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
|
|
|
6417
6403
|
"agent",
|
|
6418
6404
|
"search",
|
|
6419
6405
|
"data research",
|
|
6420
|
-
"--environment-uid",
|
|
6421
|
-
environment_uid,
|
|
6422
6406
|
"--limit",
|
|
6423
6407
|
"10",
|
|
6424
6408
|
"--timeout",
|
|
@@ -6428,7 +6412,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
|
|
|
6428
6412
|
assert result.exit_code == 0
|
|
6429
6413
|
assert captured == {
|
|
6430
6414
|
"q": "data research",
|
|
6431
|
-
"organization_environment_uid": environment_uid,
|
|
6432
6415
|
"limit": 10,
|
|
6433
6416
|
"timeout": 17,
|
|
6434
6417
|
}
|
|
@@ -6442,7 +6425,6 @@ def test_agent_search(cli_mod, runner, monkeypatch):
|
|
|
6442
6425
|
|
|
6443
6426
|
|
|
6444
6427
|
def test_agent_search_json(cli_mod, runner, monkeypatch):
|
|
6445
|
-
environment_uid = "22222222-2222-4222-8222-222222222222"
|
|
6446
6428
|
monkeypatch.setattr(cli_mod, "_require_login", lambda: {"username": "u"})
|
|
6447
6429
|
monkeypatch.setattr(
|
|
6448
6430
|
cli_mod,
|
|
@@ -6465,8 +6447,6 @@ def test_agent_search_json(cli_mod, runner, monkeypatch):
|
|
|
6465
6447
|
"agent",
|
|
6466
6448
|
"search",
|
|
6467
6449
|
"data research",
|
|
6468
|
-
"--environment-uid",
|
|
6469
|
-
environment_uid,
|
|
6470
6450
|
"--json",
|
|
6471
6451
|
],
|
|
6472
6452
|
)
|
|
@@ -4,6 +4,11 @@ import pytest
|
|
|
4
4
|
|
|
5
5
|
import mainsequence.client as msc
|
|
6
6
|
|
|
7
|
+
# Every test in this module drives a real backend over the network and needs
|
|
8
|
+
# SDK credentials, so none of them can run in CI. See `[tool.pytest.ini_options]`
|
|
9
|
+
# in pyproject.toml: `pytest` deselects them, `pytest -m live` runs them.
|
|
10
|
+
pytestmark = pytest.mark.live
|
|
11
|
+
|
|
7
12
|
|
|
8
13
|
def test_create_code_repository():
|
|
9
14
|
ds = msc.DataSource.filter(status=msc.DataSource.STATUS_AVAILABLE)[0]
|
{mainsequence-8.1.18 → mainsequence-8.1.20.dev1}/tests/test_code_repository_batch_jobs_from_file.py
RENAMED
|
@@ -6,6 +6,32 @@ import types
|
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
def _snapshot_mainsequence_modules() -> dict[str, types.ModuleType]:
|
|
10
|
+
return {
|
|
11
|
+
name: module
|
|
12
|
+
for name, module in sys.modules.items()
|
|
13
|
+
if name == "mainsequence" or name.startswith("mainsequence.")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture(autouse=True)
|
|
18
|
+
def _restore_mainsequence_modules():
|
|
19
|
+
"""Undo the stub packages this module installs into ``sys.modules``.
|
|
20
|
+
|
|
21
|
+
``_load_models_helpers_module`` replaces the real ``mainsequence`` packages
|
|
22
|
+
with stubs so ``models_helpers`` can be imported without the heavy client
|
|
23
|
+
stack. Without this fixture the stubs leak into every test module that runs
|
|
24
|
+
afterwards, and ``monkeypatch.setattr("mainsequence.client....")`` there
|
|
25
|
+
fails with ``module 'mainsequence' has no attribute 'client'``.
|
|
26
|
+
"""
|
|
27
|
+
snapshot = _snapshot_mainsequence_modules()
|
|
28
|
+
yield
|
|
29
|
+
for name in tuple(sys.modules):
|
|
30
|
+
if name == "mainsequence" or name.startswith("mainsequence."):
|
|
31
|
+
sys.modules.pop(name, None)
|
|
32
|
+
sys.modules.update(snapshot)
|
|
33
|
+
|
|
34
|
+
|
|
9
35
|
def _load_models_helpers_module():
|
|
10
36
|
repo_root = pathlib.Path(__file__).resolve().parents[1]
|
|
11
37
|
pkg_root = repo_root / "mainsequence"
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Contract for the development-release version computed by the publish workflow.
|
|
2
|
+
|
|
3
|
+
The standard these tests pin down is documented in
|
|
4
|
+
`docs/knowledge/release_process.md`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
from packaging.version import Version
|
|
11
|
+
|
|
12
|
+
from scripts import dev_release_version
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _files(*, yanked: bool = False) -> list[dict[str, object]]:
|
|
16
|
+
return [{"filename": "mainsequence-x-py3-none-any.whl", "yanked": yanked}]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_latest_final_ignores_development_and_pre_releases():
|
|
20
|
+
releases = {
|
|
21
|
+
"8.1.19": _files(),
|
|
22
|
+
"8.1.20.dev41": _files(),
|
|
23
|
+
"8.2.0rc1": _files(),
|
|
24
|
+
"8.1.19.post1": _files(),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_latest_final_ignores_releases_with_no_installable_file():
|
|
31
|
+
releases = {
|
|
32
|
+
"8.1.19": _files(),
|
|
33
|
+
"9.0.0": [],
|
|
34
|
+
"9.1.0": _files(yanked=True),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_latest_final_keeps_a_release_with_one_file_left():
|
|
41
|
+
releases = {
|
|
42
|
+
"8.1.19": _files(),
|
|
43
|
+
"8.2.0": [
|
|
44
|
+
{"filename": "mainsequence-8.2.0.tar.gz", "yanked": True},
|
|
45
|
+
{"filename": "mainsequence-8.2.0-py3-none-any.whl", "yanked": False},
|
|
46
|
+
],
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
assert dev_release_version.latest_final_version(releases) == Version("8.2.0")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_latest_final_orders_numerically_not_lexically():
|
|
53
|
+
releases = {"8.1.9": _files(), "8.1.10": _files(), "8.1.2": _files()}
|
|
54
|
+
|
|
55
|
+
assert dev_release_version.latest_final_version(releases) == Version("8.1.10")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_latest_final_skips_unparseable_versions():
|
|
59
|
+
releases = {"8.1.19": _files(), "not-a-version": _files()}
|
|
60
|
+
|
|
61
|
+
assert dev_release_version.latest_final_version(releases) == Version("8.1.19")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_latest_final_requires_at_least_one_installable_release():
|
|
65
|
+
with pytest.raises(dev_release_version.DevVersionError):
|
|
66
|
+
dev_release_version.latest_final_version({"9.0.0": []})
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_dev_version_carries_the_next_patch_number():
|
|
70
|
+
assert dev_release_version.dev_version(Version("8.1.19"), 41) == "8.1.20.dev41"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_dev_version_sorts_between_the_current_and_the_next_release():
|
|
74
|
+
computed = Version(dev_release_version.dev_version(Version("8.1.19"), 41))
|
|
75
|
+
|
|
76
|
+
assert Version("8.1.19") < computed < Version("8.1.20")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_dev_version_is_a_development_release_so_pip_skips_it_by_default():
|
|
80
|
+
computed = Version(dev_release_version.dev_version(Version("8.1.19"), 41))
|
|
81
|
+
|
|
82
|
+
assert computed.is_devrelease
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_dev_version_rejects_a_negative_run_number():
|
|
86
|
+
with pytest.raises(dev_release_version.DevVersionError):
|
|
87
|
+
dev_release_version.dev_version(Version("8.1.19"), -1)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_apply_version_rewrites_only_the_project_version():
|
|
91
|
+
pyproject = '[project]\nname = "mainsequence"\nversion = "8.1.19"\n\n[tool.other]\nversion = "1.0.0"\n'
|
|
92
|
+
|
|
93
|
+
rewritten = dev_release_version.apply_version(pyproject, "8.1.20.dev41")
|
|
94
|
+
|
|
95
|
+
assert 'version = "8.1.20.dev41"' in rewritten
|
|
96
|
+
assert rewritten.count('version = "1.0.0"') == 1
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_apply_version_refuses_a_pyproject_without_a_project_version():
|
|
100
|
+
with pytest.raises(dev_release_version.DevVersionError):
|
|
101
|
+
dev_release_version.apply_version('[project]\nname = "mainsequence"\n', "8.1.20.dev41")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_read_declared_version_reports_the_repository_version():
|
|
105
|
+
text = dev_release_version.PYPROJECT.read_text(encoding="utf-8")
|
|
106
|
+
|
|
107
|
+
declared = dev_release_version.read_declared_version(text)
|
|
108
|
+
|
|
109
|
+
assert declared is not None
|
|
110
|
+
Version(declared)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_the_repository_pyproject_accepts_a_rewritten_version():
|
|
114
|
+
text = dev_release_version.PYPROJECT.read_text(encoding="utf-8")
|
|
115
|
+
|
|
116
|
+
rewritten = dev_release_version.apply_version(text, "8.1.20.dev41")
|
|
117
|
+
|
|
118
|
+
assert dev_release_version.read_declared_version(rewritten) == "8.1.20.dev41"
|