diff --git a/setup.py b/setup.py index 3f21b9e..2622d24 100644 --- a/setup.py +++ b/setup.py @@ -43,4 +43,9 @@ def get_version() -> str: include_package_data=True, classifiers=["Topic :: Utilities", "Programming Language :: Python :: 3.9"], requires=["setuptools", "wheel", "typing", "pillow", "numpy", "requests"], + entry_points={ + "console_scripts": [ + "loadimg=loadimg.loadimg:main", + ], + }, ) diff --git a/src/loadimg/loadimg.py b/src/loadimg/loadimg.py new file mode 100644 index 0000000..3162717 --- /dev/null +++ b/src/loadimg/loadimg.py @@ -0,0 +1,49 @@ +import argparse +import sys + +try: + from .utils import load_img +except ImportError: + from utils import load_img + + +def main(): + parser = argparse.ArgumentParser( + prog="loadimg", description="Load and convert images from various sources" + ) + parser.add_argument("input", help="Input image (file path, URL, or base64 string)") + parser.add_argument( + "--output-type", + choices=["pil", "numpy", "str", "base64", "ascii", "ansi"], + default="ansi", + help="Output format (default: ansi)", + ) + parser.add_argument( + "--input-type", + choices=["auto", "base64", "file", "url", "numpy", "pil"], + default="auto", + help="Input type (default: auto)", + ) + + args = parser.parse_args() + if not hasattr(args, "input"): + parser.print_help() + exit(1) + + try: + result = load_img( + args.input, output_type=args.output_type, input_type=args.input_type + ) + if isinstance(result, str): + print(result) + else: + print(f"Image converted successfully to {args.output_type} format") + except Exception as e: + print(f"Error: {e}") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..18880d3 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,95 @@ +import unittest +import tempfile +import os +from PIL import Image +from unittest.mock import patch, MagicMock +from loadimg.loadimg import main + + +class TestCLI(unittest.TestCase): + def setUp(self): + # Create a temporary test image + self.temp_dir = tempfile.TemporaryDirectory() + self.test_image_path = os.path.join(self.temp_dir.name, "test.png") + test_image = Image.new("RGB", (100, 100), color="red") + test_image.save(self.test_image_path) + + def tearDown(self): + self.temp_dir.cleanup() + + @patch("argparse.ArgumentParser.parse_args") + def test_main_with_file_input(self, mock_args): + # Test basic file input with default settings + mock_args.return_value = MagicMock( + input=self.test_image_path, output_type="ansi", input_type="auto" + ) + + with patch("builtins.print") as mock_print: + exit_code = main() + self.assertEqual(exit_code, 0) + mock_print.assert_called() + + @patch("argparse.ArgumentParser.parse_args") + def test_main_with_invalid_file(self, mock_args): + # Test handling of non-existent file + mock_args.return_value = MagicMock( + input="nonexistent.jpg", output_type="ansi", input_type="auto" + ) + + with patch("builtins.print") as mock_print: + exit_code = main() + self.assertEqual(exit_code, 1) + mock_print.assert_called() + + @patch("argparse.ArgumentParser.parse_args") + def test_main_with_different_output_types(self, mock_args): + # Test different output types + output_types = ["ascii", "ansi", "base64", "str"] + + for output_type in output_types: + mock_args.return_value = MagicMock( + input=self.test_image_path, output_type=output_type, input_type="auto" + ) + + with patch("builtins.print") as mock_print: + exit_code = main() + self.assertEqual(exit_code, 0) + mock_print.assert_called() + + def test_cli_argument_parsing(self): + test_cases = [ + ["loadimg", self.test_image_path], + ["loadimg", self.test_image_path, "--output-type", "ascii"], + ["loadimg", self.test_image_path, "--input-type", "file"], + [ + "loadimg", + self.test_image_path, + "--output-type", + "ansi", + "--input-type", + "file", + ], + ] + + for args in test_cases: + with patch("sys.argv", args), patch("builtins.print"), patch( + "argparse.ArgumentParser._print_message" + ), patch("sys.exit") as mock_exit: + main() + # Check that sys.exit wasn't called with an error code + if mock_exit.called: + self.assertEqual(mock_exit.call_args[0][0], 0) + + def test_help_message(self): + with patch("sys.argv", ["loadimg", "--help"]), patch( + "argparse.ArgumentParser.print_help" + ) as mock_help, patch("builtins.print"), patch("sys.exit"): + try: + main() + except SystemExit: + pass + mock_help.assert_called_once() + + +if __name__ == "__main__": + unittest.main()