def test_CursorAlias_create_with_static_bitmap_and_single_size( static_bitmap, static_png) -> None: """Testing CursorAlias create method with single pixel size and static bitmap.""" alias = CursorAlias(static_bitmap) assert len(sorted(alias.alias_dir.iterdir())) == 0 alias.create((10, 10), delay=999999) for file in alias.alias_dir.iterdir(): if file.is_dir(): alias_png = list(file.iterdir())[0] assert static_png.name == alias_png.name i = Image.open(alias_png) assert i.size == (10, 10) i.close() else: assert file.stem == static_bitmap.key with file.open("r") as f: assert f.readlines() == ["10 0 0 10x10/test-0.png"] files = [f.name for f in alias.alias_dir.glob("**/*")] assert sorted(files) == sorted(["10x10", "test-0.alias", "test-0.png"]) shutil.rmtree(alias.alias_dir)
def animated_config(animated_bitmap): """Mock animated cursor config file.""" alias = CursorAlias(animated_bitmap) yield alias.create((10, 10)) shutil.rmtree(alias.alias_dir)
def test_CursorAlias_copy_alias_not_found_exception(static_bitmap) -> None: """Testing CursorAlias copy method ``FileNotFoundError`` (alias file not created) exception.""" alias = CursorAlias(static_bitmap) with pytest.raises(FileNotFoundError) as excinfo: alias.copy() assert str(excinfo.value) == alias_not_exists_err shutil.rmtree(alias.alias_dir)
def test_CursorAlias_reproduce_exception(static_bitmap) -> None: """Testing CursorAlias reproduce method ``FileNotFoundError`` (If cursor alias not created) exception.""" alias = CursorAlias(static_bitmap) with pytest.raises(FileNotFoundError) as excinfo: alias.reproduce() assert str(excinfo.value) == alias_not_exists_err shutil.rmtree(alias.alias_dir)
def test_CursorAlias_copy_with_animated_bitmap_without_args( animated_bitmap) -> None: """Testing CursorAlias copy method with animated bitmap without any arguments.""" alias = CursorAlias(animated_bitmap) alias.create((10, 10)) copy_of_alias = alias.copy() check_alias_copy(alias, copy_of_alias) shutil.rmtree(alias.alias_dir)
def test_CursorAlias_create_type_error_exception(mock_sizes, static_bitmap) -> None: """Testing CursorAlias create method ``TypeError`` exception.""" alias = CursorAlias(static_bitmap) with pytest.raises(TypeError) as excinfo: assert alias.create(sizes=mock_sizes) assert ( str(excinfo.value) == "argument 'sizes' should be Tuple[int, int] type or List[Tuple[int, int]]." ) shutil.rmtree(alias.alias_dir)
def test_CursorAlias_copy_with_animated_bitmap_with_args( animated_bitmap) -> None: """Testing CursorAlias copy method with animated bitmap with any arguments.""" alias = CursorAlias(animated_bitmap) alias.create((10, 10)) param_dst = Path(tempfile.mkdtemp()) copy_of_alias = alias.copy(param_dst) check_alias_copy(alias, copy_of_alias, param_dst=str(param_dst.absolute())) shutil.rmtree(alias.alias_dir)
def build() -> None: config = get_config() # Building for _, item in config.items(): png = item["png"] hotspot = item["hotspot"] delay = item["delay"] with CursorAlias.from_bitmap(png, hotspot) as alias: x_cfg = alias.create(X_SIZES, delay) XCursor.create(x_cfg, x_out_dir) if item.get("win_key"): win_build(item, alias) theme_name: str = "Example" comment: str = "Example theme generated from clickgen" author: str = "Kaiz Khatri" url: str = "https://github.com/ful1e5/clickgen/tree/main/examples" add_missing_xcursors(x_out_dir / "cursors", rename=True, force=True) XPackager(x_out_dir, theme_name, comment) WindowsPackager(win_out_dir, theme_name, comment, author, url)
def xbuild(config: Dict[str, Dict[str, Any]], x_out_dir: Path, info: Info) -> None: """Build `GoogleDot` cursor theme for only `X11`(UNIX) platform. :param config: `GoogleDot` configuration. :type config: ``Dict`` :param x_out_dir: Path to the output directory,\ Where the `X11` cursor theme package will generate.\ It also creates a directory if not exists. :type x_out_dir: ``pathlib.Path`` :param info: Content theme name & comment. :type info: Info """ for _, item in config.items(): with CursorAlias.from_bitmap(item["png"], item["hotspot"]) as alias: x_cfg = alias.create(item["x_sizes"], item["delay"]) print(f"Building '{x_cfg.stem}' XCursor...") XCursor.create(x_cfg, x_out_dir) add_missing_xcursor(x_out_dir / "cursors") XPackager(x_out_dir, info.name, info.comment)
def wbuild(config: Dict[str, Dict[str, Any]], win_out_dir: Path, info: Info) -> None: """Build `GoogleDot` cursor theme for only `Windows` platforms. :param config: `GoogleDot` configuration. :type config: ``Dict`` :param win_out_dir: Path to the output directory,\ Where the `Windows` cursor theme package will generate.\ It also creates a directory if not exists. :type win_out_dir: ``pathlib.Path`` :param info: Content theme name & comment. :type info: Info """ for _, item in config.items(): with CursorAlias.from_bitmap(item["png"], item["hotspot"]) as alias: alias.create(item["x_sizes"], item["delay"]) if item.get("win_key"): win_cfg = alias.reproduce( size=item["win_size"], canvas_size=item["canvas_size"], position=item["position"], delay=item["win_delay"], ).rename(item["win_key"]) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir) WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)
def win_build(item: Any, alias: CursorAlias) -> None: position = item["position"] size = item["size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_cfg = alias.reproduce(size, canvas_size, position, delay=3).rename(win_key) WindowsCursor.create(win_cfg, win_out_dir)
def test_CursorAlias_extension(static_bitmap) -> None: """Testing CursorAlias ``extension`` method.""" alias = CursorAlias(static_bitmap) alias.create((10, 10)) assert alias.alias_file.suffix == ".alias" assert alias.extension() == ".alias" alias.extension(".test") assert alias.alias_file.suffix == ".test" assert alias.extension() == ".test" shutil.rmtree(alias.alias_dir)
def test_CursorAlias_with_animated_Bitmap(animated_bitmap: Bitmap, ) -> None: """Testing CursorAlias class members value with animated bitmap.""" alias = CursorAlias(animated_bitmap) assert animated_bitmap.key in alias.prefix assert alias.prefix in str(alias.alias_dir) assert str(tempfile.tempdir) in str(alias.alias_dir) assert alias.alias_dir.exists() is True assert alias.bitmap == animated_bitmap shutil.rmtree(alias.alias_dir)
def test_CursorAlias_from_bitmap(static_png, hotspot) -> None: """Testing CursorAlias ``from_bitmap`` method.""" directory: Path with CursorAlias.from_bitmap(static_png, hotspot) as ca: assert isinstance(ca, CursorAlias) assert ca.bitmap is not None assert ca.alias_dir is not None assert ca.alias_dir.exists() is True assert ca.garbage_dirs == [] directory = ca.alias_dir assert directory.exists() is False or list(directory.iterdir()) == [] with CursorAlias.from_bitmap(static_png, hotspot) as ca1: with pytest.raises(AttributeError) as excinfo: assert ca1.alias_file is not None assert (str(excinfo.value) == "'CursorAlias' object has no attribute 'alias_file'") ca1.create((10, 10)) assert ca1.alias_file is not None
def test_CursorAlias_rename_with_animated_bitmap(image_dir) -> None: """Testing CursorAlias rename method with animated bitmap.""" animated_bitmap = Bitmap(create_test_image(image_dir, 4), (0, 0)) alias = CursorAlias(animated_bitmap) alias.create((10, 10)) old_alias = alias alias.rename("test_key") assert alias.prefix == "test_key__alias" assert (sorted( filter(lambda x: x.is_file is True, old_alias.alias_dir.glob("*/**"))) == []) assert file_tree(alias) == [ "10x10", "test_key-0.png", "test_key-1.png", "test_key-2.png", "test_key-3.png", "test_key.alias", ] with alias.alias_file.open("r") as f: assert f.readlines() == [ "10 0 0 10x10/test_key-0.png 10\n", "10 0 0 10x10/test_key-1.png 10\n", "10 0 0 10x10/test_key-2.png 10\n", "10 0 0 10x10/test_key-3.png 10", ] shutil.rmtree(alias.alias_dir)
def win_build(item: Dict[str, Any], alias: CursorAlias) -> None: position = item["position"] win_size = item["win_size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_delay = item["win_delay"] win_cfg = alias.reproduce(win_size, canvas_size, position, delay=win_delay).rename(win_key) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir)
def test_CursorAlias_create_with_static_bitmap_and_multiple_size( static_png) -> None: """Testing CursorAlias create method with multiple pixel size and static bitmap.""" static_bitmap = Bitmap(static_png, (9, 13)) mock_sizes = [(10, 10), (15, 15), (16, 16)] alias = CursorAlias(static_bitmap) assert len(sorted(alias.alias_dir.iterdir())) == 0 alias.create(mock_sizes, delay=99999) for file in alias.alias_dir.iterdir(): if file.is_dir(): alias_png = list(file.iterdir())[0] assert static_png.name == alias_png.name i = Image.open(alias_png) assert i.size in mock_sizes i.close() else: assert file.stem == static_bitmap.key with file.open("r") as f: assert f.readlines() == [ "10 4 6 10x10/test-0.png\n", "15 7 10 15x15/test-0.png\n", "16 7 10 16x16/test-0.png", ] files = [f.name for f in alias.alias_dir.glob("**/*")] assert sorted(files) == sorted([ "10x10", "15x15", "16x16", "test-0.alias", "test-0.png", # Because it's generate 3 size of png in individual directory. "test-0.png", "test-0.png", ]) shutil.rmtree(alias.alias_dir)
def test_CursorAlias_create_with_animated_bitmap_and_single_size( image_dir) -> None: """Testing CursorAlias create method with single pixel size and animated bitmap.""" animated_png = create_test_image(image_dir, 4) animated_bitmap = Bitmap(animated_png, (13, 6)) alias = CursorAlias(animated_bitmap) assert len(sorted(alias.alias_dir.iterdir())) == 0 alias.create((10, 10), delay=999999) def as_list(frames: List[Path]) -> List[str]: return sorted(map(lambda x: x.stem, frames)) for file in alias.alias_dir.iterdir(): if file.is_dir(): frames = list(file.iterdir()) assert as_list(frames) == as_list(animated_png) else: assert file.stem == animated_bitmap.key with file.open("r") as f: assert f.readlines() == [ "10 6 3 10x10/test-0.png 999999\n", "10 6 3 10x10/test-1.png 999999\n", "10 6 3 10x10/test-2.png 999999\n", "10 6 3 10x10/test-3.png 999999", ] files = [] for f in alias.alias_dir.glob("**/*"): files.append(f.name) assert sorted(files) == sorted([ "10x10", "test-0.png", "test-1.png", "test-2.png", "test-3.png", "test.alias" ]) shutil.rmtree(alias.alias_dir)
def test_add_missing_xcursors_without_rename_and_force( data, tmpdir_factory: pytest.TempdirFactory) -> None: d = tmpdir_factory.mktemp("ffff") tmp_dir = Path(d) images = create_test_image(tmp_dir, 2, key="fffff0") with CursorAlias.from_bitmap(images, (0, 0)) as alias: config_file = alias.create((10, 10), delay=2) XCursor.create(config_file, tmp_dir) x_dir = tmp_dir / "cursors" add_missing_xcursors(x_dir, data) assert list(map(lambda x: x.name, x_dir.iterdir())) == ["fffff0"] shutil.rmtree(tmp_dir)
def test_CursorAlias_extension_excpetion(static_bitmap) -> None: """Testing CursorAlias extension ``FileNotFoundError``(If alias file not created) exception.""" alias = CursorAlias(static_bitmap) with pytest.raises(FileNotFoundError) as excinfo: alias.extension() alias.extension(".test") assert str(excinfo.value) == alias_not_exists_err shutil.rmtree(alias.alias_dir)
def build(config: Dict[str, Dict[str, Any]], x_out_dir: Path, win_out_dir: Path, info: Info) -> None: """Build `Bibata Rainbow` cursor theme for `X11` & `Windows` platforms. :param config: `Bibata` configuration. :type config: Dict[str, Dict[str, Any]] :param win_out_dir: Path to the output directory,\ Where the `Windows` cursor theme package will \ generate. It also creates a directory if not exists. :type win_out_dir: Path :param info: Content theme name & comment :type info: Dict """ def win_build(item: Dict[str, Any], alias: CursorAlias) -> None: position = item["position"] win_size = item["win_size"] win_key = item["win_key"] canvas_size = item["canvas_size"] win_delay = item["win_delay"] win_cfg = alias.reproduce(win_size, canvas_size, position, delay=win_delay).rename(win_key) print(f"Building '{win_cfg.stem}' Windows Cursor...") WindowsCursor.create(win_cfg, win_out_dir) for _, item in config.items(): png = item["png"] hotspot = item["hotspot"] x_sizes = item["x_sizes"] delay = item["delay"] with CursorAlias.from_bitmap(png, hotspot) as alias: x_cfg = alias.create(x_sizes, delay) print(f"Building '{x_cfg.stem}' XCursor...") XCursor.create(x_cfg, x_out_dir) if item.get("win_key"): win_build(item, alias) add_missing_xcursor(x_out_dir / "cursors") XPackager(x_out_dir, info.name, info.comment) WindowsPackager(win_out_dir, info.name, info.comment, AUTHOR, URL)
def test_CursorAlias_copy_path_not_directory_exception(static_bitmap, test_file) -> None: """Testing CursorAlias copy method ``NotADirectoryError`` (provided path is not a directory) exception.""" alias = CursorAlias(static_bitmap) alias.create((10, 10)) with pytest.raises(NotADirectoryError) as excinfo: alias.copy(test_file) assert str( excinfo.value) == f"path '{test_file.absolute()}' is not a directory" shutil.rmtree(alias.alias_dir)
def test_static_CursorAlias_repr(static_bitmap): """Testing CursorAlias ``__repr__`` datamethod.""" alias = CursorAlias(static_bitmap) assert ( alias.__repr__() == f"{{ 'bitmap':{static_bitmap!r}, 'prefix':{alias.prefix}, 'alias_dir':{alias.alias_dir}, 'alias_file':None, 'garbage_dirs':[] }}" ) alias.create((10, 10)) assert ( alias.__repr__() == f"{{ 'bitmap':{static_bitmap!r}, 'prefix':{alias.prefix}, 'alias_dir':{alias.alias_dir}, 'alias_file':{alias.alias_file}, 'garbage_dirs':[] }}" ) shutil.rmtree(alias.alias_dir)
def test_add_missing_xcursors_with_rename_and_force( data, tmpdir_factory: pytest.TempdirFactory) -> None: d = tmpdir_factory.mktemp("ffff") tmp_dir = Path(d) images = create_test_image(tmp_dir, 2, key="ffffd") with CursorAlias.from_bitmap(images, (0, 0)) as alias: config_file = alias.create((10, 10), delay=2) XCursor.create(config_file, tmp_dir) x_dir = tmp_dir / "cursors" add_missing_xcursors(x_dir, data, rename=True) with pytest.raises(FileExistsError): add_missing_xcursors(x_dir, data, rename=True) add_missing_xcursors(x_dir, data, rename=True, force=True) assert sorted(list(map(lambda x: x.name, x_dir.iterdir()))) == sorted(["ddddd", "ffffff"]) shutil.rmtree(tmp_dir)
def test_CursorAlias_reproduce(static_png, hotspot) -> None: """Testing CursorAlias reproduce method with static bitmap.""" testing_dirs: List[Path] with CursorAlias.from_bitmap(static_png, hotspot) as alias: alias.create((10, 10)) assert alias.garbage_dirs == [] reproduced_alias = alias.reproduce(size=(24, 24), canvas_size=(32, 32), delay=44) testing_dirs = alias.garbage_dirs assert f"{alias.prefix}__garbage_bmps__" in alias.garbage_dirs[0].name assert file_tree(reproduced_alias) == [ "32x32", "test-0.alias", "test-0.png" ] assert (sorted( filter(lambda x: x.is_file is True, testing_dirs[0].glob("*/**"))) == [])
def test_static_CursorAlias_str(static_bitmap): """Testing CursorAlias ``__str__`` datamethod.""" alias = CursorAlias(static_bitmap) assert ( alias.__str__() == f"CursorAlias(bitmap={static_bitmap!s}, prefix={alias.prefix}, alias_dir={alias.alias_dir}, alias_file=None, garbage_dirs=[])" ) alias.create((10, 10)) assert ( alias.__str__() == f"CursorAlias(bitmap={static_bitmap!s}, prefix={alias.prefix}, alias_dir={alias.alias_dir}, alias_file={alias.alias_file}, garbage_dirs=[])" ) shutil.rmtree(alias.alias_dir)
def from_bitmap(cls, **kwargs) -> Path: if "png" not in kwargs: raise KeyError("argument 'png' required") elif "hotspot" not in kwargs: raise KeyError("argument 'hotspot' required") elif "size" not in kwargs: raise KeyError("argument 'size' required") elif "canvas_size" not in kwargs: raise KeyError("argument 'canvas_size' required") elif "out_dir" not in kwargs: raise KeyError("argument 'out_dir' required") position: str if "position" in kwargs: position = kwargs["position"] else: position = "center" options: Options if "options" in kwargs: options = kwargs["options"] else: options = Options() with CursorAlias.from_bitmap(kwargs["png"], kwargs["hotspot"]) as alias: if alias.bitmap.animated: if "delay" not in kwargs: raise KeyError("argument 'delay' required") else: alias.create(kwargs["size"], kwargs["delay"]) alias.reproduce(kwargs["size"], kwargs["canvas_size"], position, kwargs["delay"]) else: alias.create(kwargs["size"]) alias.reproduce(kwargs["size"], kwargs["canvas_size"], position) cursor = cls(alias.alias_file, kwargs["out_dir"], options) cursor.generate() return cursor.out
def test_WindowsCursor_create_with_animated_config(hotspot, image_dir) -> None: """Testing WindowsCursor generate animated (.ani) cursor with ``create`` \ classmethod. """ animated_png = create_test_image(image_dir, 4) with CursorAlias.from_bitmap(animated_png, hotspot) as alias: cfg = alias.create((10, 10), delay=999999999) # Cover more than one delay sets new_lines = [] with cfg.open("r") as f: lines = f.readlines() for l in lines: new_lines.append(l.replace("999999999", str(randint(20, 30)))) with cfg.open("w") as f: f.writelines(new_lines) with WindowsCursor.create(cfg, image_dir) as win: assert win.exists() is True assert win.suffix == ".ani" assert win.__sizeof__() > 0
def from_bitmap(cls, **kwargs) -> Path: if "png" not in kwargs: raise KeyError("argument 'png' required") elif "hotspot" not in kwargs: raise KeyError("argument 'hotspot' required") elif "x_sizes" not in kwargs: raise KeyError("argument 'x_sizes' required") elif "out_dir" not in kwargs: raise KeyError("argument 'out_dir' required") with CursorAlias.from_bitmap(kwargs["png"], kwargs["hotspot"]) as alias: x_cfg: Path if alias.bitmap.animated: if "delay" not in kwargs: raise KeyError("argument 'delay' required") else: x_cfg = alias.create(kwargs["x_sizes"], kwargs["delay"]) else: x_cfg = alias.create(kwargs["x_sizes"]) cursor = cls(x_cfg, kwargs["out_dir"]) cursor.generate() return cursor.out
def test_CursorAlias_rename_with_static_bitmap(static_bitmap) -> None: """Testing CursorAlias rename method with static bitmap.""" alias = CursorAlias(static_bitmap) alias.create((10, 10)) old_alias = alias alias.rename("test_key") assert alias.prefix == "test_key__alias" assert (sorted( filter(lambda x: x.is_file is True, old_alias.alias_dir.glob("*/**"))) == []) assert file_tree(alias) == ["10x10", "test_key.alias", "test_key.png"] with alias.alias_file.open("r") as f: assert f.readlines() == ["10 0 0 10x10/test_key.png"] shutil.rmtree(alias.alias_dir)