From 9dfa505849f5c2e4c24b3e4738cebbd497581436 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Dec 2025 18:39:40 +0000 Subject: [PATCH 1/7] Initial plan From aaba4d75bc5e9f03ef48a44623b2138661373dd0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Dec 2025 18:50:35 +0000 Subject: [PATCH 2/7] Fix exists command to return boolean values in JSON output - Changed INFO_EXISTS_TRUE and INFO_EXISTS_FALSE constants from strings to booleans - Updated OutputResult and FabricCLIOutput to accept bool | str message type - Added boolean-to-string conversion for text output format - Added default fallback to "text" format when format_type is None - Updated existing tests to work with boolean constants - Added new unit tests for boolean message JSON/text output Co-authored-by: ayeshurun <98805507+ayeshurun@users.noreply.github.com> --- src/fabric_cli/core/fab_constant.py | 4 +-- src/fabric_cli/core/fab_output.py | 6 ++-- src/fabric_cli/utils/fab_ui.py | 12 ++++--- tests/test_commands/test_exists.py | 19 ++++++----- tests/test_utils/test_fab_ui.py | 53 +++++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/fabric_cli/core/fab_constant.py b/src/fabric_cli/core/fab_constant.py index 2e21356b..94d3704c 100644 --- a/src/fabric_cli/core/fab_constant.py +++ b/src/fabric_cli/core/fab_constant.py @@ -196,8 +196,8 @@ COMMAND_VERSION_DESCRIPTION = "Show version information." # Info -INFO_EXISTS_TRUE = "true" -INFO_EXISTS_FALSE = "false" +INFO_EXISTS_TRUE = True +INFO_EXISTS_FALSE = False INFO_FEATURE_NOT_SUPPORTED = "Feature is not supported" # Warnings diff --git a/src/fabric_cli/core/fab_output.py b/src/fabric_cli/core/fab_output.py index a44774b0..24929e5d 100644 --- a/src/fabric_cli/core/fab_output.py +++ b/src/fabric_cli/core/fab_output.py @@ -21,7 +21,7 @@ def __init__( self, data: Optional[Any], hidden_data: Optional[List[Any]], - message: Optional[str], + message: Optional[str | bool], error_code: Optional[str] = None, ): self._data = data if isinstance(data, list) else ([data] if data else None) @@ -40,7 +40,7 @@ def hidden_data(self) -> Optional[List[str]]: return self._hidden_data @property - def message(self) -> Optional[str]: + def message(self) -> Optional[str | bool]: return self._message def to_dict(self) -> Dict[str, Any]: @@ -73,7 +73,7 @@ def __init__( output_format_type=None, show_headers=False, status: OutputStatus = OutputStatus.Success, - message: Optional[str] = None, + message: Optional[str | bool] = None, error_code: Optional[str] = None, data: Optional[Any] = None, hidden_data: Optional[Any] = None, diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index 708f7507..a9f4048f 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -90,7 +90,7 @@ def print_version(args=None): def print_output_format( args: Namespace, - message: Optional[str] = None, + message: Optional[str | bool] = None, data: Optional[Any] = None, hidden_data: Optional[Any] = None, show_headers: bool = False, @@ -124,10 +124,10 @@ def print_output_format( show_key_value_list=show_key_value_list, ) - # Get format from output or config + # Get format from output or config, default to text format_type = output.output_format_type or fab_state_config.get_config( fab_constant.FAB_OUTPUT_FORMAT - ) + ) or "text" match format_type: case "json": _print_output_format_json(output.to_json()) @@ -369,8 +369,10 @@ def _print_output_format_result_text(output: FabricCLIOutput) -> None: _print_raw_data(output_result.hidden_data) - if output_result.message: - print_done(f"{output_result.message}\n") + if output_result.message is not None: + # Convert boolean messages to string for text output + message_str = str(output_result.message).lower() if isinstance(output_result.message, bool) else output_result.message + print_done(f"{message_str}\n") def _print_raw_data(data: list[Any], to_stderr: bool = False) -> None: """ diff --git a/tests/test_commands/test_exists.py b/tests/test_commands/test_exists.py index 98747fc5..c9e2c6e4 100644 --- a/tests/test_commands/test_exists.py +++ b/tests/test_commands/test_exists.py @@ -4,6 +4,7 @@ from fabric_cli.core import fab_constant as constant from fabric_cli.core.fab_types import ItemType from tests.test_commands.data.static_test_data import StaticTestData +import json class TestExists: @@ -16,7 +17,7 @@ def test_exists_workspace_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_item_exists_success( self, item_factory, mock_print_done, cli_executor @@ -32,7 +33,7 @@ def test_exists_item_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_virtual_workspace_item_capacity_exists_success( self, mock_print_done, cli_executor, test_data: StaticTestData @@ -44,7 +45,7 @@ def test_exists_virtual_workspace_item_capacity_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_onelake_exists_success( self, item_factory, mock_print_done, cli_executor @@ -60,7 +61,7 @@ def test_exists_onelake_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_item_doesnt_exist_success( self, item_factory, mock_print_done, cli_executor @@ -77,7 +78,7 @@ def test_exists_item_doesnt_exist_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_FALSE in mock_print_done.call_args[0][0] + assert "false" in mock_print_done.call_args[0][0] def test_exists_onelake_doesnt_exist_success( self, item_factory, mock_print_done, cli_executor @@ -95,7 +96,7 @@ def test_exists_onelake_doesnt_exist_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_FALSE in mock_print_done.call_args[0][0] + assert "false" in mock_print_done.call_args[0][0] def test_exists_folder_exists_success( self, folder_factory, mock_print_done, cli_executor @@ -111,7 +112,7 @@ def test_exists_folder_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_subfolder_exists_success( self, folder_factory, mock_print_done, cli_executor @@ -128,7 +129,7 @@ def test_exists_subfolder_exists_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_TRUE in mock_print_done.call_args[0][0] + assert "true" in mock_print_done.call_args[0][0] def test_exists_folder_doesnt_exist_success( self, workspace, mock_print_done, cli_executor @@ -143,6 +144,6 @@ def test_exists_folder_doesnt_exist_success( # Assert mock_print_done.assert_called_once() - assert constant.INFO_EXISTS_FALSE in mock_print_done.call_args[0][0] + assert "false" in mock_print_done.call_args[0][0] # endregion diff --git a/tests/test_utils/test_fab_ui.py b/tests/test_utils/test_fab_ui.py index 2c35648e..2b75d7fe 100644 --- a/tests/test_utils/test_fab_ui.py +++ b/tests/test_utils/test_fab_ui.py @@ -781,3 +781,56 @@ def test_print_version_seccess(): ui.print_version() ui.print_version(None) # Just verify it doesn't crash - output verification would require mocking + + +def test_print_output_format_boolean_message_json_success( + mock_fab_set_state_config, capsys +): + """Test that boolean message values are properly serialized as JSON booleans, not strings.""" + # Setup + mock_fab_set_state_config(constant.FAB_OUTPUT_FORMAT, "json") + args = Namespace(command="exists", output_format="json") + + # Test with True boolean + ui.print_output_format(args, message=True) + captured = capsys.readouterr() + output_true = json.loads(captured.out) + + # Assert that message is a boolean true, not the string "true" + assert "result" in output_true + assert "message" in output_true["result"] + assert output_true["result"]["message"] is True + assert isinstance(output_true["result"]["message"], bool) + + # Test with False boolean + ui.print_output_format(args, message=False) + captured = capsys.readouterr() + output_false = json.loads(captured.out) + + # Assert that message is a boolean false, not the string "false" + assert "result" in output_false + assert "message" in output_false["result"] + assert output_false["result"]["message"] is False + assert isinstance(output_false["result"]["message"], bool) + + +def test_print_output_format_boolean_message_text_success(capsys): + """Test that boolean message values are properly converted to strings for text output.""" + # Setup + args = Namespace(command="exists", output_format="text") + + # Test with True boolean + ui.print_output_format(args, message=True) + captured = capsys.readouterr() + + # Assert that message is converted to string "true" + # Output goes to stdout (captured.out), not stderr + assert "true" in captured.out.lower() + + # Test with False boolean + ui.print_output_format(args, message=False) + captured = capsys.readouterr() + + # Assert that message is converted to string "false" + assert "false" in captured.out.lower() + From a07361385078c764286eb6d816434d1d9523c7d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Dec 2025 18:52:23 +0000 Subject: [PATCH 3/7] Refactor boolean message formatting into helper function Extract inline boolean-to-string conversion logic into _format_message_for_text() helper function to improve readability and maintainability. Co-authored-by: ayeshurun <98805507+ayeshurun@users.noreply.github.com> --- src/fabric_cli/utils/fab_ui.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index a9f4048f..388eafa9 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -328,6 +328,21 @@ def _safe_print_formatted_text( except (RuntimeError, AttributeError, Exception) as e: _print_fallback(escaped_text, e, to_stderr) +def _format_message_for_text(message: str | bool) -> str: + """Format a message value for text output. + + Converts boolean values to lowercase string representation. + + Args: + message: The message to format (string or boolean) + + Returns: + String representation of the message + """ + if isinstance(message, bool): + return str(message).lower() + return message + def _print_output_format_result_text(output: FabricCLIOutput) -> None: # if there is no result to print it means something went wrong @@ -371,7 +386,7 @@ def _print_output_format_result_text(output: FabricCLIOutput) -> None: if output_result.message is not None: # Convert boolean messages to string for text output - message_str = str(output_result.message).lower() if isinstance(output_result.message, bool) else output_result.message + message_str = _format_message_for_text(output_result.message) print_done(f"{message_str}\n") def _print_raw_data(data: list[Any], to_stderr: bool = False) -> None: From 6c4730e4861c9dbcdbde5da89a3d891b594a8c35 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 30 Dec 2025 19:08:43 +0000 Subject: [PATCH 4/7] Revert default fallback and explicitly set output_format in test helpers - Removed 'or "text"' fallback from print_output_format as requested - Added explicit output_format="text" to mkdir, rm, and import_cmd test helpers - This ensures tests work without relying on implicit defaults Co-authored-by: ayeshurun <98805507+ayeshurun@users.noreply.github.com> --- src/fabric_cli/utils/fab_ui.py | 4 ++-- tests/test_commands/conftest.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index 388eafa9..50ff92d6 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -124,10 +124,10 @@ def print_output_format( show_key_value_list=show_key_value_list, ) - # Get format from output or config, default to text + # Get format from output or config format_type = output.output_format_type or fab_state_config.get_config( fab_constant.FAB_OUTPUT_FORMAT - ) or "text" + ) match format_type: case "json": _print_output_format_json(output.to_json()) diff --git a/tests/test_commands/conftest.py b/tests/test_commands/conftest.py index 112924fd..5e0d3788 100644 --- a/tests/test_commands/conftest.py +++ b/tests/test_commands/conftest.py @@ -504,6 +504,7 @@ def mkdir(element_full_path, params=None): command_path="mkdir", path=element_full_path, params=params if params else ["run=true"], + output_format="text", ) context = handle_context.get_command_context(args.path, False) @@ -517,6 +518,7 @@ def rm(element_full_path): command_path="rm", path=element_full_path, force=True, + output_format="text", ) context = handle_context.get_command_context(args.path) @@ -532,6 +534,7 @@ def import_cmd(element_full_path, content_path, format=None): input=content_path, force=True, format=format, + output_format="text", ) context = handle_context.get_command_context(args.path, raise_error=False) From 810a9ecd9424184a813f89ffde6f185f6ccb31ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 31 Dec 2025 07:08:00 +0000 Subject: [PATCH 5/7] Address code review feedback: remove comments and fix config handling - Removed unnecessary comments that explain obvious code flow - Removed unused import (json) from test_exists.py - Changed test helpers to use state_config.set_config instead of args.output_format - This allows tests to override config via fixtures while helpers respect config - Cleaned up test comments that explain what's obvious from assertions Co-authored-by: aviatco <32952699+aviatco@users.noreply.github.com> --- src/fabric_cli/utils/fab_ui.py | 1 - tests/test_commands/conftest.py | 6 +++--- tests/test_commands/test_exists.py | 1 - tests/test_utils/test_fab_ui.py | 11 ----------- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/fabric_cli/utils/fab_ui.py b/src/fabric_cli/utils/fab_ui.py index 50ff92d6..de9312c9 100644 --- a/src/fabric_cli/utils/fab_ui.py +++ b/src/fabric_cli/utils/fab_ui.py @@ -385,7 +385,6 @@ def _print_output_format_result_text(output: FabricCLIOutput) -> None: if output_result.message is not None: - # Convert boolean messages to string for text output message_str = _format_message_for_text(output_result.message) print_done(f"{message_str}\n") diff --git a/tests/test_commands/conftest.py b/tests/test_commands/conftest.py index 5e0d3788..b2689ed6 100644 --- a/tests/test_commands/conftest.py +++ b/tests/test_commands/conftest.py @@ -499,12 +499,12 @@ def _create_virtual_workspace_item(type: VirtualWorkspaceType): def mkdir(element_full_path, params=None): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") + state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="mkdir", command_path="mkdir", path=element_full_path, params=params if params else ["run=true"], - output_format="text", ) context = handle_context.get_command_context(args.path, False) @@ -513,12 +513,12 @@ def mkdir(element_full_path, params=None): def rm(element_full_path): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") + state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="rm", command_path="rm", path=element_full_path, force=True, - output_format="text", ) context = handle_context.get_command_context(args.path) @@ -527,6 +527,7 @@ def rm(element_full_path): def import_cmd(element_full_path, content_path, format=None): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") + state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="import", command_path="import", @@ -534,7 +535,6 @@ def import_cmd(element_full_path, content_path, format=None): input=content_path, force=True, format=format, - output_format="text", ) context = handle_context.get_command_context(args.path, raise_error=False) diff --git a/tests/test_commands/test_exists.py b/tests/test_commands/test_exists.py index c9e2c6e4..13ea55b0 100644 --- a/tests/test_commands/test_exists.py +++ b/tests/test_commands/test_exists.py @@ -4,7 +4,6 @@ from fabric_cli.core import fab_constant as constant from fabric_cli.core.fab_types import ItemType from tests.test_commands.data.static_test_data import StaticTestData -import json class TestExists: diff --git a/tests/test_utils/test_fab_ui.py b/tests/test_utils/test_fab_ui.py index 2b75d7fe..80faf5ff 100644 --- a/tests/test_utils/test_fab_ui.py +++ b/tests/test_utils/test_fab_ui.py @@ -787,27 +787,22 @@ def test_print_output_format_boolean_message_json_success( mock_fab_set_state_config, capsys ): """Test that boolean message values are properly serialized as JSON booleans, not strings.""" - # Setup mock_fab_set_state_config(constant.FAB_OUTPUT_FORMAT, "json") args = Namespace(command="exists", output_format="json") - # Test with True boolean ui.print_output_format(args, message=True) captured = capsys.readouterr() output_true = json.loads(captured.out) - # Assert that message is a boolean true, not the string "true" assert "result" in output_true assert "message" in output_true["result"] assert output_true["result"]["message"] is True assert isinstance(output_true["result"]["message"], bool) - # Test with False boolean ui.print_output_format(args, message=False) captured = capsys.readouterr() output_false = json.loads(captured.out) - # Assert that message is a boolean false, not the string "false" assert "result" in output_false assert "message" in output_false["result"] assert output_false["result"]["message"] is False @@ -816,21 +811,15 @@ def test_print_output_format_boolean_message_json_success( def test_print_output_format_boolean_message_text_success(capsys): """Test that boolean message values are properly converted to strings for text output.""" - # Setup args = Namespace(command="exists", output_format="text") - # Test with True boolean ui.print_output_format(args, message=True) captured = capsys.readouterr() - # Assert that message is converted to string "true" - # Output goes to stdout (captured.out), not stderr assert "true" in captured.out.lower() - # Test with False boolean ui.print_output_format(args, message=False) captured = capsys.readouterr() - # Assert that message is converted to string "false" assert "false" in captured.out.lower() From 50ec5b8802d125e7997a20f923b86ecb2aed931e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 31 Dec 2025 17:20:47 +0000 Subject: [PATCH 6/7] Remove FAB_OUTPUT_FORMAT config from test helper functions - Removed state_config.set_config(FAB_OUTPUT_FORMAT, "text") from mkdir, rm, and import_cmd helpers - These helper functions should not set config that would override test-specific settings - Changed setup_default_format fixture to class scope and set config directly - This allows class-scoped workspace fixture to have format config available Co-authored-by: aviatco <32952699+aviatco@users.noreply.github.com> --- tests/test_commands/conftest.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/test_commands/conftest.py b/tests/test_commands/conftest.py index b2689ed6..1ab2ae64 100644 --- a/tests/test_commands/conftest.py +++ b/tests/test_commands/conftest.py @@ -499,7 +499,6 @@ def _create_virtual_workspace_item(type: VirtualWorkspaceType): def mkdir(element_full_path, params=None): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") - state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="mkdir", command_path="mkdir", @@ -513,7 +512,6 @@ def mkdir(element_full_path, params=None): def rm(element_full_path): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") - state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="rm", command_path="rm", @@ -527,7 +525,6 @@ def rm(element_full_path): def import_cmd(element_full_path, content_path, format=None): state_config.set_config(fab_constant.FAB_CACHE_ENABLED, "false") - state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") args = argparse.Namespace( command="import", command_path="import", @@ -555,9 +552,9 @@ def delete_cassette_if_record_mode_all(vcr_instance, cassette_name): # region mock fixtures -@pytest.fixture(autouse=True) -def setup_default_format(mock_fab_set_state_config): - mock_fab_set_state_config(fab_constant.FAB_OUTPUT_FORMAT, "text") +@pytest.fixture(autouse=True, scope="class") +def setup_default_format(): + state_config.set_config(fab_constant.FAB_OUTPUT_FORMAT, "text") @pytest.fixture(autouse=True) From f2080bac2aadaba2226729c701d624f157fda5a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 1 Jan 2026 13:39:14 +0000 Subject: [PATCH 7/7] Remove INFO_EXISTS_TRUE and INFO_EXISTS_FALSE constants - Removed INFO_EXISTS_TRUE and INFO_EXISTS_FALSE constants from fab_constant.py - Replaced usages with inline True and False in fab_fs_exists.py - Constants were only used in exists command, so inline booleans are cleaner Co-authored-by: ayeshurun <98805507+ayeshurun@users.noreply.github.com> --- src/fabric_cli/commands/fs/fab_fs_exists.py | 7 +++---- src/fabric_cli/core/fab_constant.py | 2 -- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/fabric_cli/commands/fs/fab_fs_exists.py b/src/fabric_cli/commands/fs/fab_fs_exists.py index 2e034b01..2feb8e95 100644 --- a/src/fabric_cli/commands/fs/fab_fs_exists.py +++ b/src/fabric_cli/commands/fs/fab_fs_exists.py @@ -34,7 +34,7 @@ def exec_command(args: Namespace, context: FabricElement) -> None: # Workspaces and Items def _check_if_element_exists(element: FabricElement, args: Namespace) -> None: - text_message = fab_constant.INFO_EXISTS_TRUE if element.id else fab_constant.INFO_EXISTS_FALSE + text_message = True if element.id else False utils_ui.print_output_format(args, message=text_message) @@ -49,10 +49,9 @@ def _check_if_onelake_file_or_directory_exists( args.directory = f"{workspace_id}/?recursive=false&resource=filesystem&directory={item_id}/{local_path}&getShortcutMetadata=true" try: onelake_api.list_tables_files_recursive(args) - utils_ui.print_output_format(args, message=fab_constant.INFO_EXISTS_TRUE) + utils_ui.print_output_format(args, message=True) except FabricCLIError as e: if e.status_code == fab_constant.ERROR_NOT_FOUND: - utils_ui.print_output_format(args, message=fab_constant.INFO_EXISTS_FALSE - ) + utils_ui.print_output_format(args, message=False) else: raise e diff --git a/src/fabric_cli/core/fab_constant.py b/src/fabric_cli/core/fab_constant.py index 94d3704c..a08add17 100644 --- a/src/fabric_cli/core/fab_constant.py +++ b/src/fabric_cli/core/fab_constant.py @@ -196,8 +196,6 @@ COMMAND_VERSION_DESCRIPTION = "Show version information." # Info -INFO_EXISTS_TRUE = True -INFO_EXISTS_FALSE = False INFO_FEATURE_NOT_SUPPORTED = "Feature is not supported" # Warnings