From 2693314ce05bd664064180cca3b4c06b1de1dbc8 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Mon, 8 Dec 2025 13:19:04 +0000 Subject: [PATCH 01/16] create workspace and item - return API response --- .../commands/fs/mkdir/fab_fs_mkdir_item.py | 25 ++++++++++++++++++- .../fs/mkdir/fab_fs_mkdir_workspace.py | 5 ++-- src/fabric_cli/utils/fab_cmd_mkdir_utils.py | 12 +++++++++ src/fabric_cli/utils/fab_ui.py | 6 +++-- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index 0d3490cf..8a65026a 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -16,6 +16,9 @@ def exec(item: Item, args: Namespace) -> str | None: + # Determine if this is part of a batch operation + is_root_operation = not hasattr(args, 'output_batch') + # Params params = args.params required_params, optional_params = mkdir_utils.get_params_per_item_type(item) @@ -58,8 +61,28 @@ def exec(item: Item, args: Namespace) -> str | None: response = item_api.create_item(args, json_payload, item_uri=True) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{item.name}' created") data = json.loads(response.text) + + if hasattr(args, 'output_batch') and args.output_batch['is_batching']: + # Collect operation data for batch output + args.output_batch['items'].append(data) + args.output_batch['names'].append(item.name) + + # Only print consolidated output at the end of root operation + if is_root_operation: + names_list = "' and '".join(args.output_batch['names']) + utils_ui.print_output_format( + args, + message=f"'{names_list}' created", + data=args.output_batch['items'], + show_headers=True + ) + # Clean up + delattr(args, 'output_batch') + else: + # Standard single item output for non-batched scenarios + utils_ui.print_output_format(args, message=f"'{item.name}' created", data=data, show_headers=True) + if data is not None and data.get("id"): _item_id = data["id"] item._id = _item_id diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_workspace.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_workspace.py index a389505c..7caa56db 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_workspace.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_workspace.py @@ -76,9 +76,10 @@ def exec(workspace: Workspace, args: Namespace) -> None: response = workspace_api.create_workspace(args, json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{workspace.name}' created") data = json.loads(response.text) workspace._id = data["id"] - # Add to mem_store utils_mem_store.upsert_workspace_to_cache(workspace) + + utils_ui.print_output_format(args, message=f"'{workspace.name}' created", data=data, show_headers=True) + diff --git a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py index 04d21ad3..f6a8b8f9 100644 --- a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py +++ b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py @@ -73,6 +73,8 @@ def add_type_specific_payload(item: Item, args, payload): "EventHouse not provided in params. Creating one first" ) + _initialize_batch_collection_for_dependency_creation(args) + # Create a new Event House first _eventhouse = Item( f"{item.short_name}_auto", @@ -128,6 +130,8 @@ def add_type_specific_payload(item: Item, args, payload): "Semantic Model not provided in params. Creating one first" ) + _initialize_batch_collection_for_dependency_creation(args) + # Create a new Semantic Model first _semantic_model = Item( f"{item.short_name}_auto", @@ -754,3 +758,11 @@ def find_mpe_connection(managed_private_endpoint, targetprivatelinkresourceid): return conn return None + +def _initialize_batch_collection_for_dependency_creation(args): + if not hasattr(args, 'output_batch'): + args.output_batch = { + 'items': [], + 'names': [], + 'is_batching': True + } \ No newline at end of file diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index 464dd8a5..922d5d35 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -296,6 +296,8 @@ def print_entries_unix_style( for entry in _entries: print_grey(_format_unix_style_entry(entry, fields, widths), to_stderr=False) + print_grey("", to_stderr=False) # Empty line after entries + # Others @@ -365,9 +367,9 @@ def _print_output_format_result_text(output: FabricCLIOutput) -> None: print_grey("------------------------------") _print_raw_data(output_result.hidden_data) + if output_result.message: - print_done(output_result.message) - + print_done(f"{output_result.message}\n") def _print_raw_data(data: list[Any], to_stderr: bool = False) -> None: """ From ea6be777d4cfc5e2ed60fa9db1b205ca6fbe1583 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Mon, 8 Dec 2025 13:20:30 +0000 Subject: [PATCH 02/16] tests for create workspace and item --- .../test_commands/test_mkdir/class_setup.yaml | 60 +- ...n_batched_output_kql_database_success.yaml | 515 ++++++++++++++++++ ...eation_batch_output_structure_success.yaml | 355 ++++++++++++ tests/test_commands/test_mkdir.py | 85 +++ 4 files changed, 985 insertions(+), 30 deletions(-) create mode 100644 tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml create mode 100644 tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_single_item_creation_batch_output_structure_success.yaml diff --git a/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml b/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml index a6218da0..5664b996 100644 --- a/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml +++ b/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml @@ -11,7 +11,7 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET uri: https://api.fabric.microsoft.com/v1/workspaces response: @@ -26,15 +26,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '786' + - '1018' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:13:42 GMT + - Thu, 04 Dec 2025 14:44:45 GMT Pragma: - no-cache RequestId: - - 7eaee504-fac2-4c96-8e32-dbef7efe8bde + - 99b936bd-862e-44b3-89d6-086fc618e21a Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -60,7 +60,7 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET uri: https://api.fabric.microsoft.com/v1/workspaces response: @@ -75,15 +75,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '786' + - '1018' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:13:43 GMT + - Thu, 04 Dec 2025 14:44:46 GMT Pragma: - no-cache RequestId: - - 695ed7dd-2104-488c-b0c0-845f91a5ca01 + - 4c61c57e-e960-42f6-aeb2-8e6c89d8d3b2 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -109,7 +109,7 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET uri: https://api.fabric.microsoft.com/v1/capacities response: @@ -125,15 +125,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '271' + - '807' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:13:47 GMT + - Thu, 04 Dec 2025 14:44:49 GMT Pragma: - no-cache RequestId: - - 6d155373-03fd-4f34-8d94-0820e30d54b1 + - febf31db-c1f2-43fb-a25f-9eed8378bd47 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -162,12 +162,12 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (None; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: POST uri: https://api.fabric.microsoft.com/v1/workspaces response: body: - string: '{"id": "d37f35bf-4dce-4291-9812-477382595e4b", "displayName": "fabriccli_WorkspacePerTestclass_000001", + string: '{"id": "d27a72f5-2f85-45f8-905f-264fe3136668", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}' headers: Access-Control-Expose-Headers: @@ -181,13 +181,13 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:13:55 GMT + - Thu, 04 Dec 2025 14:44:58 GMT Location: - - https://api.fabric.microsoft.com/v1/workspaces/d37f35bf-4dce-4291-9812-477382595e4b + - https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668 Pragma: - no-cache RequestId: - - 9950b60b-464a-477d-a0ee-0c15c5cdf936 + - c8cfec0b-3ead-4b92-84a9-ccc8220e09d1 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -213,13 +213,13 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (ls; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (mkdir; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET uri: https://api.fabric.microsoft.com/v1/workspaces response: body: string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": - "My workspace", "description": "", "type": "Personal"}, {"id": "d37f35bf-4dce-4291-9812-477382595e4b", + "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' headers: @@ -230,15 +230,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '820' + - '1052' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:14:33 GMT + - Thu, 04 Dec 2025 14:53:12 GMT Pragma: - no-cache RequestId: - - c1d25fd0-3982-4b9e-bf98-dc785f01a79d + - 2be305ef-62db-4154-ad24-6ee888274f08 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -264,9 +264,9 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (ls; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (mkdir; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET - uri: https://api.fabric.microsoft.com/v1/workspaces/d37f35bf-4dce-4291-9812-477382595e4b/items + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items response: body: string: '{"value": []}' @@ -282,11 +282,11 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 25 Sep 2025 09:14:34 GMT + - Thu, 04 Dec 2025 14:53:13 GMT Pragma: - no-cache RequestId: - - 4faadd3b-1048-460e-9bc3-fc8be2360ac1 + - ed38c4e0-63ee-4816-aa88-45036bac86b2 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -314,9 +314,9 @@ interactions: Content-Type: - application/json User-Agent: - - ms-fabric-cli/1.1.0 (ls; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) + - ms-fabric-cli/1.2.0 (mkdir; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: DELETE - uri: https://api.fabric.microsoft.com/v1/workspaces/d37f35bf-4dce-4291-9812-477382595e4b + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668 response: body: string: '' @@ -332,11 +332,11 @@ interactions: Content-Type: - application/octet-stream Date: - - Thu, 25 Sep 2025 09:14:35 GMT + - Thu, 04 Dec 2025 14:53:14 GMT Pragma: - no-cache RequestId: - - 5c18271d-3f2c-4a89-a672-d0707be7a579 + - 8fb71d95-a519-4f55-b9f0-203eb09ffe03 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: diff --git a/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml new file mode 100644 index 00000000..6fb1b215 --- /dev/null +++ b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml @@ -0,0 +1,515 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces + response: + body: + string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": + "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", + "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created + by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '1052' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:44:58 GMT + Pragma: + - no-cache + RequestId: + - 5bedf7fc-d729-47e2-a22f-da2470961957 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + response: + body: + string: '{"value": []}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '32' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:44:59 GMT + Pragma: + - no-cache + RequestId: + - db8c5ec7-6192-4c1c-93a5-16946e0f50b9 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + response: + body: + string: '{"value": []}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '32' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:44:59 GMT + Pragma: + - no-cache + RequestId: + - 6c7de197-4156-4698-9a38-e8974873816a + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: '{"description": "Created by fab", "displayName": "fabcli000001_auto", "type": + "Eventhouse", "folderId": null}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '113' + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: POST + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/eventhouses + response: + body: + string: '{"id": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8", "type": "Eventhouse", + "displayName": "fabcli000001_auto", "description": "Created by fab", "workspaceId": + "d27a72f5-2f85-45f8-905f-264fe3136668"}' + headers: + Access-Control-Expose-Headers: + - RequestId,ETag + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '173' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:45:04 GMT + ETag: + - '""' + Pragma: + - no-cache + RequestId: + - c3ce116b-8606-4f70-971c-4dc6c9f394ea + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 201 + message: Created +- request: + body: '{"description": "Created by fab", "displayName": "fabcli000001", "type": + "KQLDatabase", "folderId": null, "creationPayload": {"databaseType": "ReadWrite", + "parentEventhouseItemId": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8"}}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '225' + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: POST + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/kqlDatabases + response: + body: + string: 'null' + headers: + Access-Control-Expose-Headers: + - RequestId,Location,Retry-After,ETag,x-ms-operation-id + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '24' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:45:05 GMT + ETag: + - '""' + Location: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780 + Pragma: + - no-cache + RequestId: + - aed3b2ef-8f74-4028-9535-2a6f69173e09 + Retry-After: + - '20' + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + x-ms-operation-id: + - 49a2c265-9be7-450c-8182-2877ae149780 + status: + code: 202 + message: Accepted +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780 + response: + body: + string: '{"status": "Succeeded", "createdTimeUtc": "2025-12-04T14:45:05.4742049", + "lastUpdatedTimeUtc": "2025-12-04T14:45:12.100619", "percentComplete": 100, + "error": null}' + headers: + Access-Control-Expose-Headers: + - RequestId,Location,x-ms-operation-id + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '130' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:45:26 GMT + Location: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780/result + Pragma: + - no-cache + RequestId: + - 12f43964-89ac-463c-bd77-579bd9ba6801 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + x-ms-operation-id: + - 49a2c265-9be7-450c-8182-2877ae149780 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780/result + response: + body: + string: '{"id": "48459580-630f-4553-a481-71c5251d1930", "type": "KQLDatabase", + "displayName": "fabcli000001", "description": "Created by fab", "workspaceId": + "d27a72f5-2f85-45f8-905f-264fe3136668"}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Type: + - application/json + Date: + - Thu, 04 Dec 2025 14:45:27 GMT + Pragma: + - no-cache + RequestId: + - 2ce05e55-6f5a-461d-95d5-a6088a04ed36 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + Transfer-Encoding: + - chunked + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces + response: + body: + string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": + "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", + "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created + by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '1052' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:53:11 GMT + Pragma: + - no-cache + RequestId: + - c5e18920-59a5-4b08-9592-894257c5acfd + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + response: + body: + string: '{"value": [{"id": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8", "type": "Eventhouse", + "displayName": "fabcli000001_auto", "description": "Created by fab", "workspaceId": + "d27a72f5-2f85-45f8-905f-264fe3136668"}, {"id": "0b36ab47-9918-486c-b1af-42c832e9638a", + "type": "KQLDatabase", "displayName": "fabcli000001_auto", "description": + "fabcli000001_auto", "workspaceId": "d27a72f5-2f85-45f8-905f-264fe3136668"}, + {"id": "48459580-630f-4553-a481-71c5251d1930", "type": "KQLDatabase", "displayName": + "fabcli000001", "description": "Created by fab", "workspaceId": "d27a72f5-2f85-45f8-905f-264fe3136668"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '261' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:53:11 GMT + Pragma: + - no-cache + RequestId: + - 8080f277-4b9a-4468-93c7-4b6079a365fd + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: DELETE + uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items/de2f991e-c9e9-4a50-9d70-d971b8ce39b8 + response: + body: + string: '' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '0' + Content-Type: + - application/octet-stream + Date: + - Thu, 04 Dec 2025 14:53:12 GMT + Pragma: + - no-cache + RequestId: + - f5d6abac-b705-453c-aef9-1bcf98e82e44 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_single_item_creation_batch_output_structure_success.yaml b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_single_item_creation_batch_output_structure_success.yaml new file mode 100644 index 00000000..c1a180b1 --- /dev/null +++ b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_single_item_creation_batch_output_structure_success.yaml @@ -0,0 +1,355 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces + response: + body: + string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": + "My workspace", "description": "", "type": "Personal"}, {"id": "6af05968-8605-4178-a09a-23829d1f9ee0", + "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created + by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '1053' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:40 GMT + Pragma: + - no-cache + RequestId: + - 4624fc45-d3f5-469f-8d50-2a0e6d38eb5a + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/6af05968-8605-4178-a09a-23829d1f9ee0/items + response: + body: + string: '{"value": []}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '32' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:40 GMT + Pragma: + - no-cache + RequestId: + - 40449fcc-44bb-4119-adfd-79bfdf8a87f9 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/6af05968-8605-4178-a09a-23829d1f9ee0/items + response: + body: + string: '{"value": []}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '32' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:41 GMT + Pragma: + - no-cache + RequestId: + - 85d2e888-3929-452b-b9a7-a7d892740b54 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: '{"description": "Created by fab", "displayName": "fabcli000001", "type": + "Lakehouse", "folderId": null}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '107' + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: POST + uri: https://api.fabric.microsoft.com/v1/workspaces/6af05968-8605-4178-a09a-23829d1f9ee0/lakehouses + response: + body: + string: '{"id": "375a206a-39fd-4396-a95a-447d4746d746", "type": "Lakehouse", + "displayName": "fabcli000001", "description": "Created by fab", "workspaceId": + "6af05968-8605-4178-a09a-23829d1f9ee0"}' + headers: + Access-Control-Expose-Headers: + - RequestId,ETag + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '167' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:47 GMT + ETag: + - '""' + Pragma: + - no-cache + RequestId: + - 7761d018-5b93-4a7f-a12c-c75db6434d03 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces + response: + body: + string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": + "My workspace", "description": "", "type": "Personal"}, {"id": "6af05968-8605-4178-a09a-23829d1f9ee0", + "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created + by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '1053' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:47 GMT + Pragma: + - no-cache + RequestId: + - 381d9bef-5d66-4c2e-a2eb-d51ee762a6e4 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: GET + uri: https://api.fabric.microsoft.com/v1/workspaces/6af05968-8605-4178-a09a-23829d1f9ee0/items + response: + body: + string: '{"value": [{"id": "375a206a-39fd-4396-a95a-447d4746d746", "type": "Lakehouse", + "displayName": "fabcli000001", "description": "Created by fab", "workspaceId": + "6af05968-8605-4178-a09a-23829d1f9ee0"}]}' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '179' + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 04 Dec 2025 14:43:48 GMT + Pragma: + - no-cache + RequestId: + - 88c858d2-b2d8-4c21-85a7-a33bdbbeea76 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + Content-Type: + - application/json + User-Agent: + - ms-fabric-cli-test/1.2.0 + method: DELETE + uri: https://api.fabric.microsoft.com/v1/workspaces/6af05968-8605-4178-a09a-23829d1f9ee0/items/375a206a-39fd-4396-a95a-447d4746d746 + response: + body: + string: '' + headers: + Access-Control-Expose-Headers: + - RequestId + Cache-Control: + - no-store, must-revalidate, no-cache + Content-Encoding: + - gzip + Content-Length: + - '0' + Content-Type: + - application/octet-stream + Date: + - Thu, 04 Dec 2025 14:43:49 GMT + Pragma: + - no-cache + RequestId: + - 1b5a10b8-4e6c-4b6c-b4ce-b09aa25a8254 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - deny + home-cluster-uri: + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/ + request-redirected: + - 'true' + status: + code: 200 + message: OK +version: 1 diff --git a/tests/test_commands/test_mkdir.py b/tests/test_commands/test_mkdir.py index 916c66ac..8f05c9fb 100644 --- a/tests/test_commands/test_mkdir.py +++ b/tests/test_commands/test_mkdir.py @@ -1839,6 +1839,91 @@ def test_mkdir_folder_name_already_exists_failure( # endregion + # region Batch Output Tests + def test_mkdir_single_item_creation_batch_output_structure_success( + self, workspace, cli_executor, mock_print_done, mock_questionary_print, vcr_instance, cassette_name + ): + """Test that single item creation uses batched output structure.""" + # Setup + lakehouse_display_name = generate_random_string(vcr_instance, cassette_name) + lakehouse_full_path = cli_path_join( + workspace.full_path, f"{lakehouse_display_name}.{ItemType.LAKEHOUSE}" + ) + + # Execute command + cli_executor.exec_command(f"mkdir {lakehouse_full_path}") + + # Assert - verify output structure + mock_print_done.assert_called_once() + call_args = mock_print_done.call_args + assert lakehouse_display_name in call_args[0][0] + assert "created" in call_args[0][0] + + # Verify headers and values in mock_questionary_print.mock_calls + # Look for the table output with headers + output_calls = [str(call) for call in mock_questionary_print.mock_calls] + table_output = "\n".join(output_calls) + + # Check for standard table headers + assert "id" in table_output or "ID" in table_output + assert "type" in table_output or "Type" in table_output + assert "displayName" in table_output or "DisplayName" in table_output + assert "workspaceId" in table_output or "WorkspaceId" in table_output + + # Check for actual values + assert lakehouse_display_name in table_output + assert "Lakehouse" in table_output + assert workspace.id in table_output + + # Cleanup + rm(lakehouse_full_path) + + def test_mkdir_dependency_creation_batched_output_kql_database_success( + self, workspace, cli_executor, mock_print_done, mock_questionary_print, vcr_instance, cassette_name + ): + """Test that KQL Database creation with EventHouse dependency produces batched output.""" + # Setup + kqldatabase_display_name = generate_random_string(vcr_instance, cassette_name) + kqldatabase_full_path = cli_path_join( + workspace.full_path, f"{kqldatabase_display_name}.{ItemType.KQL_DATABASE}" + ) + + # Execute command (this will create EventHouse dependency automatically) + cli_executor.exec_command(f"mkdir {kqldatabase_full_path}") + + # Assert - should have two print_done calls (one consolidated output with both items) + # The current implementation may still have separate calls, but data should be collected + assert mock_print_done.call_count >= 1 + + + # Verify both items are mentioned in output + all_calls = [call.args[0] for call in mock_print_done.call_args_list] + all_output = " ".join(all_calls) + assert f"'{kqldatabase_display_name}_auto.{ItemType.EVENTHOUSE.value}' and '{kqldatabase_display_name}.{ItemType.KQL_DATABASE.value}' created" in all_output + + # Verify headers and values in mock_questionary_print.mock_calls for batched output + output_calls = [str(call) for call in mock_questionary_print.mock_calls] + table_output = "\n".join(output_calls) + + # Check for standard table headers (should appear once for consolidated table) + assert "id" in table_output or "ID" in table_output + assert "type" in table_output or "Type" in table_output + assert "displayName" in table_output or "DisplayName" in table_output + assert "workspaceId" in table_output or "WorkspaceId" in table_output + + # Check for both item values in the output + assert kqldatabase_display_name in table_output + assert f"{kqldatabase_display_name}_auto" in table_output # EventHouse dependency name + assert "KQLDatabase" in table_output or "KQL_DATABASE" in table_output + assert "Eventhouse" in table_output or "EVENTHOUSE" in table_output + assert workspace.id in table_output + + # Cleanup - removing parent eventhouse removes the kqldatabase as well + eventhouse_full_path = kqldatabase_full_path.removesuffix(".KQLDatabase") + "_auto.Eventhouse" + rm(eventhouse_full_path) + + # endregion + # region Helper Methods def mkdir(path, params=["run=true"]): From 0e3f6685069857ed58a160c8da2564d8e4feddef Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Mon, 8 Dec 2025 14:51:32 +0000 Subject: [PATCH 03/16] return API response in create capacity --- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_capacity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_capacity.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_capacity.py index 4d6ea0c5..f2f8a4a6 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_capacity.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_capacity.py @@ -71,7 +71,7 @@ def exec(capacity: VirtualWorkspaceItem, args: Namespace) -> None: response = capacity_api.create_capacity(args, payload=json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{capacity.name}' created") + utils_ui.print_output_format(args, message=f"'{capacity.name}' created", data=json.loads(response.text), show_headers=True) # In here we use a different approach since the id responded by the API is not the same as the id we use in the code # The id in the response is the fully qualified azure resource ID for the resource From 5050016dc522aed3dc092702ee2be2dba04c8f3c Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Mon, 8 Dec 2025 15:05:42 +0000 Subject: [PATCH 04/16] return API response in create Managedidentity --- .../commands/fs/mkdir/fab_fs_mkdir_managedidentity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedidentity.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedidentity.py index bbf7f294..e4286fea 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedidentity.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedidentity.py @@ -25,10 +25,10 @@ def exec(managed_identity: VirtualItem, args: Namespace) -> None: utils_ui.print_grey(f"Creating a new Managed Identity...") response = managed_identity_api.provision_managed_identity(args) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{managed_identity.name}' created") data = json.loads(response.text) managed_identity._id = data["servicePrincipalId"] # Add to mem_store utils_mem_store.upsert_managed_identity_to_cache(managed_identity) + utils_ui.print_output_format(args, message=f"'{managed_identity.name}' created", data=data, show_headers=True) From 45a78e6c7bca299e4d1e20d27c309c23efc9d7c3 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Mon, 8 Dec 2025 15:35:43 +0000 Subject: [PATCH 05/16] return API response in create folder,domain,connection,sparkpool --- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_connection.py | 4 ++-- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py | 3 +-- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_folder.py | 2 +- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_sparkpool.py | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_connection.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_connection.py index fd28d23a..78bf2614 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_connection.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_connection.py @@ -125,9 +125,9 @@ def exec(connection: VirtualWorkspaceItem, args: Namespace) -> None: response = connection_api.create_connection(args, payload=json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{connection.name}' created") - data = json.loads(response.text) + utils_ui.print_output_format(args, message=f"'{connection.name}' created", data=data, show_headers=True) + connection._id = data["id"] # Add to mem_store diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py index 8fbc832f..78babe62 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_domain.py @@ -49,9 +49,8 @@ def exec(domain: VirtualWorkspaceItem, args: Namespace) -> None: response = domain_api.create_domain(args, payload=json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{domain.name}' created") - data = json.loads(response.text) + utils_ui.print_output_format(args, message=f"'{domain.name}' created", data=data, show_headers=True) domain._id = data["id"] diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_folder.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_folder.py index c2eca535..336d5978 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_folder.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_folder.py @@ -36,8 +36,8 @@ def exec(folder: Folder, args: Namespace) -> str | None: response = folder_api.create_folder(args, json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{folder.name}' created") data = json.loads(response.text) + utils_ui.print_output_format(args, message=f"'{folder.name}' created", data=data, show_headers=True) if data is not None and data.get("id"): _folder_id = data["id"] folder._id = _folder_id diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_sparkpool.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_sparkpool.py index 15ad0b44..a58bb67d 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_sparkpool.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_sparkpool.py @@ -83,10 +83,9 @@ def exec(spark_pool: VirtualItem, args: Namespace) -> None: utils_ui.print_grey(f"Creating a new Spark Pool...") response = sparkpool_api.create_spark_pool(args, payload=json_payload) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{spark_pool.name}' created") - data = json.loads(response.text) spark_pool._id = data["id"] # Add to mem_store utils_mem_store.upsert_spark_pool_to_cache(spark_pool) + utils_ui.print_output_format(args, message=f"'{spark_pool.name}' created", data=data, show_headers=True) From a0d2046a64f1b34dbcc7002232f75d3e83467e3c Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 9 Dec 2025 12:37:23 +0000 Subject: [PATCH 06/16] return API response in create externaldatashare,gateway,managedprivateendpoint --- .../commands/fs/mkdir/fab_fs_mkdir_externaldatashare.py | 4 +--- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_gateway.py | 3 +-- .../commands/fs/mkdir/fab_fs_mkdir_managedprivateendpoint.py | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_externaldatashare.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_externaldatashare.py index 2dbc8f15..63788dc3 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_externaldatashare.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_externaldatashare.py @@ -71,9 +71,7 @@ def exec(external_data_share: VirtualItem, args: Namespace) -> None: item.name, external_data_share.id ) - utils_ui.print_output_format( - args, message=f"'{external_data_share.name}' created" - ) + utils_ui.print_output_format(args, message=f"'{external_data_share.name}' created", data=data, show_headers=True) # Add to mem_store utils_mem_store.upsert_external_data_share_to_cache(external_data_share, item) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_gateway.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_gateway.py index 502e2283..1354a447 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_gateway.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_gateway.py @@ -95,9 +95,8 @@ def exec(gateway: VirtualWorkspaceItem, args: Namespace) -> None: response = gateway_api.create_gateway(args, payload=json.dumps(payload)) if response.status_code in (200, 201): - utils_ui.print_output_format(args, message=f"'{gateway.name}' created") - data = json.loads(response.text) + utils_ui.print_output_format(args, message=f"'{gateway.name}' created", data=data, show_headers=True) gateway._id = data["id"] # Add to mem_store diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedprivateendpoint.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedprivateendpoint.py index 890e253d..9c2534ad 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedprivateendpoint.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_managedprivateendpoint.py @@ -128,4 +128,4 @@ def exec(managed_private_endpoint: VirtualItem, args: Namespace) -> None: fab_constant.ERROR_OPERATION_FAILED, ) - utils_ui.print_output_format(args, message=result_message) + utils_ui.print_output_format(args, message=result_message, data=data, show_headers=True) From 208e8411bf950ec58d780364c43188bb86ed5f72 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 9 Dec 2025 14:12:01 +0000 Subject: [PATCH 07/16] fix failures in the tests --- src/fabric_cli/utils/fab_ui.py | 4 +--- tests/test_commands/test_mkdir.py | 32 ++++++++++++++++--------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index 3b63fc11..708f7507 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -144,7 +144,7 @@ def print_done(text: str, to_stderr: bool = False) -> None: # Escape the text to avoid HTML injection and parsing issues escaped_text = html.escape(text) _safe_print_formatted_text( - f"* {escaped_text}", escaped_text, to_stderr + f"\n* {escaped_text}", escaped_text, to_stderr ) @@ -296,8 +296,6 @@ def print_entries_unix_style( for entry in _entries: print_grey(_format_unix_style_entry(entry, fields, widths), to_stderr=False) - print_grey("", to_stderr=False) # Empty line after entries - # Others diff --git a/tests/test_commands/test_mkdir.py b/tests/test_commands/test_mkdir.py index f8379051..3a4a1fe2 100644 --- a/tests/test_commands/test_mkdir.py +++ b/tests/test_commands/test_mkdir.py @@ -177,7 +177,8 @@ def test_mkdir_kqldatabase_without_creation_payload_success( # Assert # call_count is 2 because the first call is for the parent eventhouse and the second call is for the kqldatabase assert upsert_item_to_cache.call_count == 2 - assert mock_print_done.call_count == 2 + # print call_count is 1 because we batch the result of the first call for the parent eventhouse and the second call for the kqldatabase + assert mock_print_done.call_count == 1 assert any( kqldatabase_display_name in call.args[0] for call in mock_print_done.mock_calls @@ -1315,10 +1316,10 @@ def test_mkdir_connection_with_onpremises_gateway_params_success( # Assert mock_print_done.assert_called() assert mock_print_done.call_count == 1 - assert f"'{connection_display_name}.Connection' created" == mock_print_done.call_args[0][0] + assert f"'{connection_display_name}.Connection' created\n" == mock_print_done.call_args[0][0] mock_print_done.reset_mock() - + # Cleanup rm(connection_full_path) @@ -1338,13 +1339,13 @@ def test_mkdir_connection_with_onpremises_gateway_params_ignore_params_success( ) cli_executor.exec_command( - f'mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values=\'[{{"gatewayId":"{test_data.onpremises_gateway_details.id}","encryptedCredentials":"{test_data.onpremises_gateway_details.encrypted_credentials}","ignoreParameters":"ignoreParameters"}}]\'' + f"mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values='[{{\"gatewayId\":\"{test_data.onpremises_gateway_details.id}\",\"encryptedCredentials\":\"{test_data.onpremises_gateway_details.encrypted_credentials}\",\"ignoreParameters\":\"ignoreParameters\"}}]'" ) # Assert mock_print_done.assert_called() assert mock_print_done.call_count == 1 - assert f"'{connection_display_name}.Connection' created" == mock_print_done.call_args[0][0] + assert f"'{connection_display_name}.Connection' created\n" == mock_print_done.call_args[0][0] mock_print_warning.assert_called() assert mock_print_warning.call_count == 1 @@ -1353,6 +1354,7 @@ def test_mkdir_connection_with_onpremises_gateway_params_ignore_params_success( # Cleanup rm(connection_full_path) + def test_mkdir_connection_with_onpremises_gateway_params_failure( self, cli_executor, @@ -1395,7 +1397,7 @@ def test_mkdir_connection_with_onpremises_gateway_params_failure( # Test 3: Execute command with missing encryptedCredentials params in one of the values cli_executor.exec_command( - f'mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values=\'[{{"gatewayId":"{test_data.onpremises_gateway_details.id}","encryptedCredentials":"{test_data.onpremises_gateway_details.encrypted_credentials}"}},{{"encryptedCredentials":"{test_data.onpremises_gateway_details.encrypted_credentials}"}}]\'' + f"mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values='[{{\"gatewayId\":\"{test_data.onpremises_gateway_details.id}\",\"encryptedCredentials\":\"{test_data.onpremises_gateway_details.encrypted_credentials}\"}},{{\"encryptedCredentials\":\"{test_data.onpremises_gateway_details.encrypted_credentials}\"}}]'" ) # Assert @@ -1408,7 +1410,7 @@ def test_mkdir_connection_with_onpremises_gateway_params_failure( # Test 4: Execute command with invalid json format for values cli_executor.exec_command( - f"mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values='[{{gatewayId:{test_data.onpremises_gateway_details.id}, encryptedCredentials:{test_data.onpremises_gateway_details.encrypted_credentials}}}]'" + f"mkdir {connection_full_path} -P gatewayId={test_data.onpremises_gateway_details.id},connectionDetails.type=SQL,connectivityType=OnPremisesGateway,connectionDetails.parameters.server={test_data.sql_server.server}.database.windows.net,connectionDetails.parameters.database={test_data.sql_server.database},credentialDetails.type=Basic,credentialDetails.values=[{{gatewayId:{test_data.onpremises_gateway_details.id}, encryptedCredentials:{test_data.onpremises_gateway_details.encrypted_credentials}}}]" ) # Assert @@ -1715,7 +1717,7 @@ def test_mkdir_workspace_verify_stderr_stdout_messages_text_format_success( ) # Verify exact stdout message in text format - assert captured.out.strip() == f"* '{workspace_display_name}.Workspace' created" + assert f"* '{workspace_display_name}.Workspace' created" in captured.out.strip() # Cleanup rm(workspace_full_path) @@ -1755,36 +1757,38 @@ def test_mkdir_workspace_verify_stderr_stdout_messages_json_format_success( # endregion # region Folders - + def test_mkdir_item_in_folder_listing_success( self, workspace, cli_executor, mock_print_done, mock_questionary_print, mock_fab_set_state_config, vcr_instance, cassette_name ): # Enable folder listing mock_fab_set_state_config(constant.FAB_FOLDER_LISTING_ENABLED, "true") + # Setup folder_name = f"{generate_random_string(vcr_instance, cassette_name)}.Folder" folder_full_path = cli_path_join(workspace.full_path, folder_name) - + # Create folder cli_executor.exec_command(f"mkdir {folder_full_path}") mock_print_done.assert_called_once() mock_print_done.reset_mock() - + # Create notebook in folder notebook_name = f"{generate_random_string(vcr_instance, cassette_name)}.Notebook" notebook_full_path = cli_path_join(folder_full_path, notebook_name) cli_executor.exec_command(f"mkdir {notebook_full_path}") - + # Verify notebook appears in folder listing cli_executor.exec_command(f"ls {folder_full_path}") printed_output = mock_questionary_print.call_args[0][0] assert notebook_name in printed_output - + # Cleanup rm(notebook_full_path) rm(folder_full_path) + def test_mkdir_folder_success(self, workspace, cli_executor, mock_print_done): # Setup folder_display_name = "folder" @@ -1870,7 +1874,6 @@ def test_mkdir_single_item_creation_batch_output_structure_success( # Check for actual values assert lakehouse_display_name in table_output assert "Lakehouse" in table_output - assert workspace.id in table_output # Cleanup rm(lakehouse_full_path) @@ -1913,7 +1916,6 @@ def test_mkdir_dependency_creation_batched_output_kql_database_success( assert f"{kqldatabase_display_name}_auto" in table_output # EventHouse dependency name assert "KQLDatabase" in table_output or "KQL_DATABASE" in table_output assert "Eventhouse" in table_output or "EVENTHOUSE" in table_output - assert workspace.id in table_output # Cleanup - removing parent eventhouse removes the kqldatabase as well eventhouse_full_path = kqldatabase_full_path.removesuffix(".KQLDatabase") + "_auto.Eventhouse" From 626c04414e2404e6d331417f363d3f7573abb90c Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 9 Dec 2025 14:14:19 +0000 Subject: [PATCH 08/16] add changie --- .changes/unreleased/added-20251209-141353.yaml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changes/unreleased/added-20251209-141353.yaml diff --git a/.changes/unreleased/added-20251209-141353.yaml b/.changes/unreleased/added-20251209-141353.yaml new file mode 100644 index 00000000..08f63c2c --- /dev/null +++ b/.changes/unreleased/added-20251209-141353.yaml @@ -0,0 +1,3 @@ +kind: added +body: Include API response data in the output. +time: 2025-12-09T14:13:53.030608891Z From 7507f245ab884d4e9af730ff6d2497c2d2403c1e Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 9 Dec 2025 15:51:44 +0000 Subject: [PATCH 09/16] Fix tests --- tests/test_commands/test_cd.py | 2 +- tests/test_commands/test_cp.py | 6 +++--- tests/test_commands/test_export.py | 2 +- tests/test_commands/test_labels.py | 4 ++-- tests/test_commands/test_ls.py | 5 +++++ tests/test_commands/test_mv.py | 2 +- tests/test_commands/test_rm.py | 5 +++-- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/tests/test_commands/test_cd.py b/tests/test_commands/test_cd.py index ac4794b8..de9c0885 100644 --- a/tests/test_commands/test_cd.py +++ b/tests/test_commands/test_cd.py @@ -17,7 +17,7 @@ def test_cd_tenant_success(self, mock_print_done, cli_executor): cli_executor.exec_command("cd /") # Assert - mock_print_done.assert_called_once_with("Switched to root") + mock_print_done.assert_called_once_with("Switched to root\n") assert isinstance(Context().context, Tenant) def test_cd_workspace_success(self, workspace, mock_print_done, cli_executor): diff --git a/tests/test_commands/test_cp.py b/tests/test_commands/test_cp.py index 5e4ce6d4..b29866dc 100644 --- a/tests/test_commands/test_cp.py +++ b/tests/test_commands/test_cp.py @@ -64,7 +64,7 @@ def test_cp_workspace_to_workspace_non_recursive_success( mock_print_warning.assert_called_once() assert any( call.args[0] - == f"2 items copied successfully from {ws1.full_path} to {ws2.full_path}" + == f"2 items copied successfully from {ws1.full_path} to {ws2.full_path}\n" for call in mock_print_done.mock_calls ) @@ -146,7 +146,7 @@ def test_cp_workspace_to_workspace_recursive_success( mock_print_warning.assert_called_once() assert any( call.args[0] - == f"2 items and 1 folders copied successfully from {ws1.full_path} to {ws2.full_path}" + == f"2 items and 1 folders copied successfully from {ws1.full_path} to {ws2.full_path}\n" for call in mock_print_done.mock_calls ) @@ -254,7 +254,7 @@ def test_cp_workspace_to_folder_success( mock_print_warning.assert_called_once() assert any( call.args[0] - == f"2 items copied successfully from {ws1.full_path} to {f2.full_path}" + == f"2 items copied successfully from {ws1.full_path} to {f2.full_path}\n" for call in mock_print_done.mock_calls ) diff --git a/tests/test_commands/test_export.py b/tests/test_commands/test_export.py index 7077d377..dd52add9 100644 --- a/tests/test_commands/test_export.py +++ b/tests/test_commands/test_export.py @@ -136,7 +136,7 @@ def test_export_workspace_success( mock_print_done.assert_called() mock_print_warning.assert_called_once() assert any( - call.args[0] == "2 items exported successfully" + call.args[0] == "2 items exported successfully\n" for call in mock_print_done.mock_calls ) diff --git a/tests/test_commands/test_labels.py b/tests/test_commands/test_labels.py index 86b8e962..784dd9c1 100644 --- a/tests/test_commands/test_labels.py +++ b/tests/test_commands/test_labels.py @@ -92,7 +92,7 @@ def test_labels_set_lakehouse_with_force_success( cli_executor.exec_command(command_str) # Assert mock_print_done.assert_called() - assert mock_print_done.call_args[0][0] == "Label set" + assert mock_print_done.call_args[0][0] == "Label set\n" def test_labels_set_without_force_success( self, item_factory, cli_executor, mock_print_done, test_data: StaticTestData @@ -111,7 +111,7 @@ def test_labels_set_without_force_success( cli_executor.exec_command(command_str) # Assert mock_print_done.assert_called() - assert mock_print_done.call_args[0][0] == "Label set" + assert mock_print_done.call_args[0][0] == "Label set\n" def test_labels_set_invalid_label_name_failure( self, diff --git a/tests/test_commands/test_ls.py b/tests/test_commands/test_ls.py index dd9819c4..dfef0bc5 100644 --- a/tests/test_commands/test_ls.py +++ b/tests/test_commands/test_ls.py @@ -596,6 +596,8 @@ def test_ls_spark_pool_success( workspace.full_path, str(VirtualItemContainerType.SPARK_POOL) ) + mock_questionary_print.reset_mock() + # Test 1: without args cli_executor.exec_command(f"ls {sparkpools_path}") @@ -690,6 +692,9 @@ def test_ls_managed_private_endpoints_success( managed_private_endpoints_path = cli_path_join( workspace.full_path, str(VirtualItemContainerType.MANAGED_PRIVATE_ENDPOINT) ) + + mock_questionary_print.reset_mock() + # Test 1: without args cli_executor.exec_command(f"ls {managed_private_endpoints_path}") diff --git a/tests/test_commands/test_mv.py b/tests/test_commands/test_mv.py index 844af71a..eb17667d 100644 --- a/tests/test_commands/test_mv.py +++ b/tests/test_commands/test_mv.py @@ -395,7 +395,7 @@ def test_mv_item_from_workspace_to_workspace_when_item_already_exists( # Assert mock_print_done.assert_called() assert any( - call.args[0] == "Move completed" for call in mock_print_done.mock_calls + call.args[0] == "Move completed\n" for call in mock_print_done.mock_calls ) mock_questionary_print.reset_mock() diff --git a/tests/test_commands/test_rm.py b/tests/test_commands/test_rm.py index 91567add..d68f82e7 100644 --- a/tests/test_commands/test_rm.py +++ b/tests/test_commands/test_rm.py @@ -252,7 +252,8 @@ def test_rm_workspace_without_force_success( ) mkdir(notebook.full_path) mock_print_done.reset_mock() - + mock_questionary_print.reset_mock() + with ( patch("questionary.checkbox") as mock_checkbox, patch("questionary.confirm") as mock_confirm, @@ -270,7 +271,7 @@ def test_rm_workspace_without_force_success( mock_questionary_print.assert_called() mock_print_done.assert_called() _assert_strings_in_mock_calls( - ["1 items deleted successfully"], True, mock_print_done.mock_calls + ["1 items deleted successfully\n"], True, mock_print_done.mock_calls ) _assert_strings_in_mock_calls( [notebook.display_name], True, mock_print_done.mock_calls From 55adc319e4fd7ca5d0768f658309ecddccbf84a5 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 9 Dec 2025 16:06:19 +0000 Subject: [PATCH 10/16] Fix more tests --- tests/test_commands/test_api.py | 4 ++++ tests/test_commands/test_mv.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_commands/test_api.py b/tests/test_commands/test_api.py index 708d7517..7b000712 100644 --- a/tests/test_commands/test_api.py +++ b/tests/test_commands/test_api.py @@ -200,6 +200,8 @@ def _build_api_args(endpoint, method, params, input, audience, headers, show_hea def _get_workspace_id(workspace, mock_questionary_print) -> str: + mock_questionary_print.reset_mock() + api("workspaces", "get") # Extract the arguments passed to the mock @@ -219,6 +221,8 @@ def _get_workspace_id(workspace, mock_questionary_print) -> str: def _get_item_id(workspace_id, item, mock_questionary_print) -> str: + mock_questionary_print.reset_mock() + api(f"workspaces/{workspace_id}/items", "get") # Extract the arguments passed to the mock diff --git a/tests/test_commands/test_mv.py b/tests/test_commands/test_mv.py index eb17667d..5563ff6b 100644 --- a/tests/test_commands/test_mv.py +++ b/tests/test_commands/test_mv.py @@ -545,7 +545,7 @@ def test_mv_item_within_workspace_rename_success( # Assert mock_print_done.assert_called() assert any( - call.args[0] == "Move completed" for call in mock_print_done.mock_calls + call.args[0] == "Move completed\n" for call in mock_print_done.mock_calls ) mock_questionary_print.reset_mock() From fc07b21c9a4bde335a079f75c530141c66172cb6 Mon Sep 17 00:00:00 2001 From: aviatco <32952699+aviatco@users.noreply.github.com> Date: Wed, 10 Dec 2025 09:03:33 +0200 Subject: [PATCH 11/16] Update src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py Co-authored-by: Alon Yeshurun <98805507+ayeshurun@users.noreply.github.com> --- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index 8a65026a..a2955b69 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -63,7 +63,7 @@ def exec(item: Item, args: Namespace) -> str | None: if response.status_code in (200, 201): data = json.loads(response.text) - if hasattr(args, 'output_batch') and args.output_batch['is_batching']: + if not is_root_operation and args.output_batch['is_batching'] == True: # Collect operation data for batch output args.output_batch['items'].append(data) args.output_batch['names'].append(item.name) From 181faeb2a59a6b1db8ccfee84d8116c07e1eb326 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Wed, 10 Dec 2025 14:37:40 +0000 Subject: [PATCH 12/16] remove is_batching flag. update create item message --- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py | 8 +++++--- src/fabric_cli/utils/fab_cmd_mkdir_utils.py | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index 8a65026a..b9eaa524 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -63,17 +63,19 @@ def exec(item: Item, args: Namespace) -> str | None: if response.status_code in (200, 201): data = json.loads(response.text) - if hasattr(args, 'output_batch') and args.output_batch['is_batching']: + if hasattr(args, 'output_batch'): # Collect operation data for batch output args.output_batch['items'].append(data) args.output_batch['names'].append(item.name) # Only print consolidated output at the end of root operation if is_root_operation: - names_list = "' and '".join(args.output_batch['names']) + names = args.output_batch['names'] + names_list = f"'{names[0]}' and '{names[1]}'" if len(names) == 2 else "'" + "', '".join(names[:-1]) + f"' and '{names[-1]}'" + utils_ui.print_output_format( args, - message=f"'{names_list}' created", + message=f"{names_list} created", data=args.output_batch['items'], show_headers=True ) diff --git a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py index f6a8b8f9..03555dae 100644 --- a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py +++ b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py @@ -763,6 +763,5 @@ def _initialize_batch_collection_for_dependency_creation(args): if not hasattr(args, 'output_batch'): args.output_batch = { 'items': [], - 'names': [], - 'is_batching': True + 'names': [] } \ No newline at end of file From 6ceff53748474760b6d711e983d1170b6b360a06 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Wed, 10 Dec 2025 14:38:07 +0000 Subject: [PATCH 13/16] new recording for test_mkdir_dependency_creation_batched_output_kql_database_success --- .../test_commands/test_mkdir/class_setup.yaml | 48 ++++----- ...n_batched_output_kql_database_success.yaml | 102 +++++++++--------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml b/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml index 5664b996..1ff92c9e 100644 --- a/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml +++ b/tests/test_commands/recordings/test_commands/test_mkdir/class_setup.yaml @@ -26,15 +26,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '1018' + - '1054' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:45 GMT + - Wed, 10 Dec 2025 14:36:12 GMT Pragma: - no-cache RequestId: - - 99b936bd-862e-44b3-89d6-086fc618e21a + - 46a76ab9-a143-451d-90d0-f9fd657b1dbe Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -75,15 +75,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '1018' + - '1054' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:46 GMT + - Wed, 10 Dec 2025 14:36:12 GMT Pragma: - no-cache RequestId: - - 4c61c57e-e960-42f6-aeb2-8e6c89d8d3b2 + - b659f6f2-2390-446e-ab99-3b090cc635ea Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -125,15 +125,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '807' + - '873' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:49 GMT + - Wed, 10 Dec 2025 14:36:16 GMT Pragma: - no-cache RequestId: - - febf31db-c1f2-43fb-a25f-9eed8378bd47 + - b23c547e-bc6b-4a83-9f1c-248239404869 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -167,7 +167,7 @@ interactions: uri: https://api.fabric.microsoft.com/v1/workspaces response: body: - string: '{"id": "d27a72f5-2f85-45f8-905f-264fe3136668", "displayName": "fabriccli_WorkspacePerTestclass_000001", + string: '{"id": "b14aea11-ff9f-40fd-a872-21636c090395", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}' headers: Access-Control-Expose-Headers: @@ -177,17 +177,17 @@ interactions: Content-Encoding: - gzip Content-Length: - - '188' + - '187' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:58 GMT + - Wed, 10 Dec 2025 14:36:23 GMT Location: - - https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668 + - https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395 Pragma: - no-cache RequestId: - - c8cfec0b-3ead-4b92-84a9-ccc8220e09d1 + - 97eb7f80-4e28-4201-ae75-5570c99ad930 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -219,7 +219,7 @@ interactions: response: body: string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": - "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", + "My workspace", "description": "", "type": "Personal"}, {"id": "b14aea11-ff9f-40fd-a872-21636c090395", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' headers: @@ -230,15 +230,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '1052' + - '1091' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:53:12 GMT + - Wed, 10 Dec 2025 14:36:57 GMT Pragma: - no-cache RequestId: - - 2be305ef-62db-4154-ad24-6ee888274f08 + - 9d54b68b-5a87-439a-90ba-d343916423c8 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -266,7 +266,7 @@ interactions: User-Agent: - ms-fabric-cli/1.2.0 (mkdir; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: GET - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/items response: body: string: '{"value": []}' @@ -282,11 +282,11 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:53:13 GMT + - Wed, 10 Dec 2025 14:36:58 GMT Pragma: - no-cache RequestId: - - ed38c4e0-63ee-4816-aa88-45036bac86b2 + - 353f6d45-0cff-4127-a474-a9b1317790c4 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -316,7 +316,7 @@ interactions: User-Agent: - ms-fabric-cli/1.2.0 (mkdir; Linux; x86_64; 6.6.87.2-microsoft-standard-WSL2) method: DELETE - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668 + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395 response: body: string: '' @@ -332,11 +332,11 @@ interactions: Content-Type: - application/octet-stream Date: - - Thu, 04 Dec 2025 14:53:14 GMT + - Wed, 10 Dec 2025 14:36:59 GMT Pragma: - no-cache RequestId: - - 8fb71d95-a519-4f55-b9f0-203eb09ffe03 + - 522420d0-d4cb-4d93-8a13-a5a9bdf30d41 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: diff --git a/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml index 6fb1b215..700eb674 100644 --- a/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml +++ b/tests/test_commands/recordings/test_commands/test_mkdir/test_mkdir_dependency_creation_batched_output_kql_database_success.yaml @@ -17,7 +17,7 @@ interactions: response: body: string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": - "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", + "My workspace", "description": "", "type": "Personal"}, {"id": "b14aea11-ff9f-40fd-a872-21636c090395", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' headers: @@ -28,15 +28,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '1052' + - '1091' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:58 GMT + - Wed, 10 Dec 2025 14:36:24 GMT Pragma: - no-cache RequestId: - - 5bedf7fc-d729-47e2-a22f-da2470961957 + - f818cb76-08dc-4c58-8642-b69407adb76f Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -64,7 +64,7 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: GET - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/items response: body: string: '{"value": []}' @@ -80,11 +80,11 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:59 GMT + - Wed, 10 Dec 2025 14:36:25 GMT Pragma: - no-cache RequestId: - - db8c5ec7-6192-4c1c-93a5-16946e0f50b9 + - 97548fdd-8553-47f0-b61a-44b16f94918a Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -112,7 +112,7 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: GET - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/items response: body: string: '{"value": []}' @@ -128,11 +128,11 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:44:59 GMT + - Wed, 10 Dec 2025 14:36:26 GMT Pragma: - no-cache RequestId: - - 6c7de197-4156-4698-9a38-e8974873816a + - c7ddd3b5-2a3a-4f14-b053-c1c790d66a7d Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -163,12 +163,12 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: POST - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/eventhouses + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/eventhouses response: body: - string: '{"id": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8", "type": "Eventhouse", + string: '{"id": "8520e310-fb97-41f4-b9f7-2cf2e55b2c12", "type": "Eventhouse", "displayName": "fabcli000001_auto", "description": "Created by fab", "workspaceId": - "d27a72f5-2f85-45f8-905f-264fe3136668"}' + "b14aea11-ff9f-40fd-a872-21636c090395"}' headers: Access-Control-Expose-Headers: - RequestId,ETag @@ -177,17 +177,17 @@ interactions: Content-Encoding: - gzip Content-Length: - - '173' + - '174' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:45:04 GMT + - Wed, 10 Dec 2025 14:36:30 GMT ETag: - '""' Pragma: - no-cache RequestId: - - c3ce116b-8606-4f70-971c-4dc6c9f394ea + - c77fb138-52b9-4aa4-b70e-7e093a481aa0 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -204,7 +204,7 @@ interactions: - request: body: '{"description": "Created by fab", "displayName": "fabcli000001", "type": "KQLDatabase", "folderId": null, "creationPayload": {"databaseType": "ReadWrite", - "parentEventhouseItemId": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8"}}' + "parentEventhouseItemId": "8520e310-fb97-41f4-b9f7-2cf2e55b2c12"}}' headers: Accept: - '*/*' @@ -219,7 +219,7 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: POST - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/kqlDatabases + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/kqlDatabases response: body: string: 'null' @@ -235,15 +235,15 @@ interactions: Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:45:05 GMT + - Wed, 10 Dec 2025 14:36:32 GMT ETag: - '""' Location: - - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780 + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/c08a8a14-a569-47a1-ada7-dcaf3a904eb3 Pragma: - no-cache RequestId: - - aed3b2ef-8f74-4028-9535-2a6f69173e09 + - cf117302-8705-4b5b-96df-1f579c5f3d20 Retry-After: - '20' Strict-Transport-Security: @@ -257,7 +257,7 @@ interactions: request-redirected: - 'true' x-ms-operation-id: - - 49a2c265-9be7-450c-8182-2877ae149780 + - c08a8a14-a569-47a1-ada7-dcaf3a904eb3 status: code: 202 message: Accepted @@ -275,11 +275,11 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: GET - uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780 + uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/c08a8a14-a569-47a1-ada7-dcaf3a904eb3 response: body: - string: '{"status": "Succeeded", "createdTimeUtc": "2025-12-04T14:45:05.4742049", - "lastUpdatedTimeUtc": "2025-12-04T14:45:12.100619", "percentComplete": 100, + string: '{"status": "Succeeded", "createdTimeUtc": "2025-12-10T14:36:31.7079906", + "lastUpdatedTimeUtc": "2025-12-10T14:36:44.5531228", "percentComplete": 100, "error": null}' headers: Access-Control-Expose-Headers: @@ -289,17 +289,17 @@ interactions: Content-Encoding: - gzip Content-Length: - - '130' + - '132' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:45:26 GMT + - Wed, 10 Dec 2025 14:36:53 GMT Location: - - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780/result + - https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/c08a8a14-a569-47a1-ada7-dcaf3a904eb3/result Pragma: - no-cache RequestId: - - 12f43964-89ac-463c-bd77-579bd9ba6801 + - 4f001d02-e052-4cad-859f-f336cb482c16 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -307,7 +307,7 @@ interactions: X-Frame-Options: - deny x-ms-operation-id: - - 49a2c265-9be7-450c-8182-2877ae149780 + - c08a8a14-a569-47a1-ada7-dcaf3a904eb3 status: code: 200 message: OK @@ -325,12 +325,12 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: GET - uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/49a2c265-9be7-450c-8182-2877ae149780/result + uri: https://wabi-us-central-b-primary-redirect.analysis.windows.net/v1/operations/c08a8a14-a569-47a1-ada7-dcaf3a904eb3/result response: body: - string: '{"id": "48459580-630f-4553-a481-71c5251d1930", "type": "KQLDatabase", + string: '{"id": "b18bd8f6-f619-441c-99d3-3e76e097938c", "type": "KQLDatabase", "displayName": "fabcli000001", "description": "Created by fab", "workspaceId": - "d27a72f5-2f85-45f8-905f-264fe3136668"}' + "b14aea11-ff9f-40fd-a872-21636c090395"}' headers: Access-Control-Expose-Headers: - RequestId @@ -341,11 +341,11 @@ interactions: Content-Type: - application/json Date: - - Thu, 04 Dec 2025 14:45:27 GMT + - Wed, 10 Dec 2025 14:36:54 GMT Pragma: - no-cache RequestId: - - 2ce05e55-6f5a-461d-95d5-a6088a04ed36 + - 75721e04-1663-4e5a-81e4-ee4ecae62ed7 Strict-Transport-Security: - max-age=31536000; includeSubDomains Transfer-Encoding: @@ -375,7 +375,7 @@ interactions: response: body: string: '{"value": [{"id": "3634a139-2c9e-4205-910b-3b089a31be47", "displayName": - "My workspace", "description": "", "type": "Personal"}, {"id": "d27a72f5-2f85-45f8-905f-264fe3136668", + "My workspace", "description": "", "type": "Personal"}, {"id": "b14aea11-ff9f-40fd-a872-21636c090395", "displayName": "fabriccli_WorkspacePerTestclass_000001", "description": "Created by fab", "type": "Workspace", "capacityId": "00000000-0000-0000-0000-000000000004"}]}' headers: @@ -386,15 +386,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '1052' + - '1091' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:53:11 GMT + - Wed, 10 Dec 2025 14:36:55 GMT Pragma: - no-cache RequestId: - - c5e18920-59a5-4b08-9592-894257c5acfd + - 8457d766-4cd3-473a-bde0-8e347258ff4a Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -422,16 +422,16 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: GET - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/items response: body: - string: '{"value": [{"id": "de2f991e-c9e9-4a50-9d70-d971b8ce39b8", "type": "Eventhouse", + string: '{"value": [{"id": "8520e310-fb97-41f4-b9f7-2cf2e55b2c12", "type": "Eventhouse", "displayName": "fabcli000001_auto", "description": "Created by fab", "workspaceId": - "d27a72f5-2f85-45f8-905f-264fe3136668"}, {"id": "0b36ab47-9918-486c-b1af-42c832e9638a", + "b14aea11-ff9f-40fd-a872-21636c090395"}, {"id": "608c7f46-8cc0-4f34-8608-7ce19f6a4839", "type": "KQLDatabase", "displayName": "fabcli000001_auto", "description": - "fabcli000001_auto", "workspaceId": "d27a72f5-2f85-45f8-905f-264fe3136668"}, - {"id": "48459580-630f-4553-a481-71c5251d1930", "type": "KQLDatabase", "displayName": - "fabcli000001", "description": "Created by fab", "workspaceId": "d27a72f5-2f85-45f8-905f-264fe3136668"}]}' + "fabcli000001_auto", "workspaceId": "b14aea11-ff9f-40fd-a872-21636c090395"}, + {"id": "b18bd8f6-f619-441c-99d3-3e76e097938c", "type": "KQLDatabase", "displayName": + "fabcli000001", "description": "Created by fab", "workspaceId": "b14aea11-ff9f-40fd-a872-21636c090395"}]}' headers: Access-Control-Expose-Headers: - RequestId @@ -440,15 +440,15 @@ interactions: Content-Encoding: - gzip Content-Length: - - '261' + - '262' Content-Type: - application/json; charset=utf-8 Date: - - Thu, 04 Dec 2025 14:53:11 GMT + - Wed, 10 Dec 2025 14:36:56 GMT Pragma: - no-cache RequestId: - - 8080f277-4b9a-4468-93c7-4b6079a365fd + - 1f5702a8-62dc-4c40-bf32-53eff33c5d59 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: @@ -478,7 +478,7 @@ interactions: User-Agent: - ms-fabric-cli-test/1.2.0 method: DELETE - uri: https://api.fabric.microsoft.com/v1/workspaces/d27a72f5-2f85-45f8-905f-264fe3136668/items/de2f991e-c9e9-4a50-9d70-d971b8ce39b8 + uri: https://api.fabric.microsoft.com/v1/workspaces/b14aea11-ff9f-40fd-a872-21636c090395/items/8520e310-fb97-41f4-b9f7-2cf2e55b2c12 response: body: string: '' @@ -494,11 +494,11 @@ interactions: Content-Type: - application/octet-stream Date: - - Thu, 04 Dec 2025 14:53:12 GMT + - Wed, 10 Dec 2025 14:36:57 GMT Pragma: - no-cache RequestId: - - f5d6abac-b705-453c-aef9-1bcf98e82e44 + - 31d2cc18-dd35-4f8f-bbee-996b59d0b923 Strict-Transport-Security: - max-age=31536000; includeSubDomains X-Content-Type-Options: From c840da37cabca82dd1bf84bedbfa64bf4548a107 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Thu, 11 Dec 2025 10:21:54 +0000 Subject: [PATCH 14/16] Fix output_batch validation --- src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index 3f7f307a..b9eaa524 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -63,7 +63,7 @@ def exec(item: Item, args: Namespace) -> str | None: if response.status_code in (200, 201): data = json.loads(response.text) - if not is_root_operation: + if hasattr(args, 'output_batch'): # Collect operation data for batch output args.output_batch['items'].append(data) args.output_batch['names'].append(item.name) From 8195d3c87eee9dec69cb14f68cb0f06ebb6d0656 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Tue, 23 Dec 2025 10:54:53 +0000 Subject: [PATCH 15/16] add docstring --- .../commands/fs/mkdir/fab_fs_mkdir_item.py | 15 +++++++++++++++ src/fabric_cli/utils/fab_cmd_mkdir_utils.py | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index b9eaa524..6cbc459a 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -16,6 +16,21 @@ def exec(item: Item, args: Namespace) -> str | None: + """Execute the creation of a Microsoft Fabric item. + + Handles two scenarios based on is_root_operation: + - **Root operation** (is_root_operation = True): User-initiated standalone creation. + Shows individual output, handles dependencies, and cleans up batch collection. + - **Batch operation** (is_root_operation = False): Part of dependency creation chain. + Operates silently, collects results for consolidated output by root operation. + + Args: + item (Item): The Fabric item to be created + args (Namespace): Command arguments, may contain 'output_batch' for batch operations + + Returns: + str | None: Created item ID if successful, None if failed + """ # Determine if this is part of a batch operation is_root_operation = not hasattr(args, 'output_batch') diff --git a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py index 03555dae..97c06de9 100644 --- a/src/fabric_cli/utils/fab_cmd_mkdir_utils.py +++ b/src/fabric_cli/utils/fab_cmd_mkdir_utils.py @@ -760,6 +760,24 @@ def find_mpe_connection(managed_private_endpoint, targetprivatelinkresourceid): return None def _initialize_batch_collection_for_dependency_creation(args): + """Initialize batch collection for scenarios where dependent items need to be created automatically. + + This method is used when creating items that have dependencies that don't exist yet, such as: + - Creating a KQL Database without an EventHouse (auto-creates EventHouse first) + - Creating a Report without a Semantic Model (auto-creates Semantic Model first) + + The batch collection allows multiple related items to be created in sequence and then + display a consolidated output message showing all items that were created together. + + Args: + args (Namespace): The command arguments namespace that will be augmented with + 'output_batch' attribute containing 'items' and 'names' lists + to collect creation results. + + Note: + This method only initializes the batch collection if it doesn't already exist, + ensuring it's safe to call multiple times during a dependency creation chain. + """ if not hasattr(args, 'output_batch'): args.output_batch = { 'items': [], From 2a7fd366b1d682b8b1a11181a4f92d4bf919cd60 Mon Sep 17 00:00:00 2001 From: aviat cohen Date: Wed, 24 Dec 2025 07:43:52 +0000 Subject: [PATCH 16/16] update docstring --- .../commands/fs/mkdir/fab_fs_mkdir_item.py | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py index 6cbc459a..a64778a4 100644 --- a/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py +++ b/src/fabric_cli/commands/fs/mkdir/fab_fs_mkdir_item.py @@ -16,20 +16,33 @@ def exec(item: Item, args: Namespace) -> str | None: - """Execute the creation of a Microsoft Fabric item. - - Handles two scenarios based on is_root_operation: - - **Root operation** (is_root_operation = True): User-initiated standalone creation. - Shows individual output, handles dependencies, and cleans up batch collection. - - **Batch operation** (is_root_operation = False): Part of dependency creation chain. - Operates silently, collects results for consolidated output by root operation. - + """ + Execute the creation of a Microsoft Fabric item. + + This method supports items that may require creating additional dependent + artifacts (e.g., a Report that implicitly creates a SemanticModel). + Output behavior differs depending on whether the current call represents the + user‑requested creation or an internally triggered dependency. + + Two execution modes: + - **Root operation** (`is_root_operation=True`): + Represents the item explicitly requested by the user. + Handles creation of the item and any required dependencies. + Collects and returns a consolidated output for all created artifacts. + + - **Dependency operation** (`is_root_operation=False`): + Represents an item created implicitly as part of another item's dependency chain. + Runs silently and contributes its result to the root operation’s batch output, + without producing standalone output. + Args: - item (Item): The Fabric item to be created - args (Namespace): Command arguments, may contain 'output_batch' for batch operations - + item (Item): The Fabric item to be created. + args (Namespace): Command arguments. May include `output_batch` used to + accumulate results during dependency operations. + Returns: - str | None: Created item ID if successful, None if failed + str | None: The created item ID for root operations, or None for dependency + operations or failed creations. """ # Determine if this is part of a batch operation is_root_operation = not hasattr(args, 'output_batch')