From bb10fdcd98156355b798c63618405c7f4a73b3c1 Mon Sep 17 00:00:00 2001 From: 12rambau Date: Fri, 18 Nov 2022 07:50:56 +0000 Subject: [PATCH 1/6] fix: set icon and text as traits in btn --- .pre-commit-config.yaml | 2 +- sepal_ui/sepalwidgets/btn.py | 68 ++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7999786c..971728a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: black stages: [commit] - - repo: 'https://gitlab.com/pycqa/flake8' + - repo: 'https://github.com/pycqa/flake8' rev: 3.9.2 hooks: - id: flake8 diff --git a/sepal_ui/sepalwidgets/btn.py b/sepal_ui/sepalwidgets/btn.py index c6437d86..bbd29a95 100644 --- a/sepal_ui/sepalwidgets/btn.py +++ b/sepal_ui/sepalwidgets/btn.py @@ -1,6 +1,9 @@ +import warnings from pathlib import Path import ipyvuetify as v +from deprecated.sphinx import deprecated +from traitlets import Unicode, observe from sepal_ui.scripts import utils as su from sepal_ui.sepalwidgets.sepalwidget import SepalWidget @@ -14,27 +17,78 @@ class Btn(v.Btn, SepalWidget): the color will be defaulted to 'primary' and can be changed afterward according to your need Args: + msg (str, optional): the text to display in the btn + gliph (str, optional): the full name of any mdi/fa icon text (str, optional): the text to display in the btn icon (str, optional): the full name of any mdi/fa icon kwargs (dict, optional): any parameters from v.Btn. if set, 'children' will be overwritten. + + .. deprecated:: 2.13 + ``text`` and ``icon`` will be replaced by ``msg`` and ``gliph`` to avoid duplicating ipyvuetify trait. """ v_icon = None "v.Icon: the icon in the btn" - def __init__(self, text="Click", icon="", **kwargs): + gliph = Unicode("").tag(sync=True) + "traitlet.Unicode: the name of the icon" + + msg = Unicode("").tag(sync=True) + "traitlet.Unicode: the text of the btn" + + def __init__(self, msg="click", gliph="", **kwargs): + + # deprecation in 2.13 of text and icon + # as they already exist in the ipyvuetify Btn traits (as booleans) + if "text" in kwargs: + if isinstance(kwargs["text"], str): + msg = kwargs.pop("text") + warnings.warn('"text" is deprecated, please use "msg" instead') + if "icon" in kwargs: + if isinstance(kwargs["icon"], str): + gliph = kwargs.pop("icon") + warnings.warn('"icon" is deprecated, please use "gliph" instead') # create the default v_icon self.v_icon = v.Icon(left=True, children=[""]) - self.set_icon(icon) # set the default parameters kwargs["color"] = kwargs.pop("color", "primary") - kwargs["children"] = [self.v_icon, text] + kwargs["children"] = [self.v_icon, self.msg] # call the constructor super().__init__(**kwargs) + self.gliph = gliph + self.msg = msg + + @observe("gliph") + def _set_icon(self, change): + """ + Set a new icon. If the icon is set to "", then it's hidden + """ + new_icon = change["new"] + self.v_icon.children = [new_icon] + + # hide the component to avoid the right padding + if not new_icon: + su.hide_component(self.v_icon) + else: + su.show_component(self.v_icon) + + return self + + @observe("msg") + def _set_text(self, change): + """ + Set the text of the btn + """ + + self.children = [self.v_icon, change["new"]] + + return self + + @deprecated(version="2.14", reason="Replace by the private _set_icon") def set_icon(self, icon=""): """ set a new icon. If the icon is set to "", then it's hidden. @@ -45,13 +99,7 @@ def set_icon(self, icon=""): Return: self """ - self.v_icon.children = [icon] - - if not icon: - su.hide_component(self.v_icon) - else: - su.show_component(self.v_icon) - + self.icon = icon return self def toggle_loading(self): From a594f3f418352ed8203506e7f39e4acdf65b3a00 Mon Sep 17 00:00:00 2001 From: 12rambau Date: Mon, 21 Nov 2022 20:26:41 +0000 Subject: [PATCH 2/6] test: the new btn traits --- sepal_ui/sepalwidgets/btn.py | 14 +++++++------- tests/test_Btn.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/sepal_ui/sepalwidgets/btn.py b/sepal_ui/sepalwidgets/btn.py index bbd29a95..183a943c 100644 --- a/sepal_ui/sepalwidgets/btn.py +++ b/sepal_ui/sepalwidgets/btn.py @@ -36,7 +36,7 @@ class Btn(v.Btn, SepalWidget): msg = Unicode("").tag(sync=True) "traitlet.Unicode: the text of the btn" - def __init__(self, msg="click", gliph="", **kwargs): + def __init__(self, msg="Click", gliph="", **kwargs): # deprecation in 2.13 of text and icon # as they already exist in the ipyvuetify Btn traits (as booleans) @@ -63,15 +63,15 @@ def __init__(self, msg="click", gliph="", **kwargs): self.msg = msg @observe("gliph") - def _set_icon(self, change): + def _set_gliph(self, change): """ Set a new icon. If the icon is set to "", then it's hidden """ - new_icon = change["new"] - self.v_icon.children = [new_icon] + new_gliph = change["new"] + self.v_icon.children = [new_gliph] # hide the component to avoid the right padding - if not new_icon: + if not new_gliph: su.hide_component(self.v_icon) else: su.show_component(self.v_icon) @@ -88,7 +88,7 @@ def _set_text(self, change): return self - @deprecated(version="2.14", reason="Replace by the private _set_icon") + @deprecated(version="2.14", reason="Replace by the private _set_gliph") def set_icon(self, icon=""): """ set a new icon. If the icon is set to "", then it's hidden. @@ -99,7 +99,7 @@ def set_icon(self, icon=""): Return: self """ - self.icon = icon + self.gliph = icon return self def toggle_loading(self): diff --git a/tests/test_Btn.py b/tests/test_Btn.py index 407c0e3b..7f7b612c 100644 --- a/tests/test_Btn.py +++ b/tests/test_Btn.py @@ -50,6 +50,34 @@ def test_toggle_loading(self, btn): return + def test_set_gliph(self, btn): + + # new gliph + gliph = "fas fa-folder" + btn.gliph = gliph + + assert isinstance(btn.v_icon, v.Icon) + assert btn.v_icon.children[0] == gliph + + # change existing icon + gliph = "fas fa-file" + btn.gliph = gliph + assert btn.v_icon.children[0] == gliph + + return + + def test_test_msg(self, btn): + + # test the initial text + assert btn.children[1] == "Click" + + # update msg + msg = "New message" + btn.msg = msg + assert btn.children[1] == msg + + return + @pytest.fixture def btn(self): """Create a simple btn""" From 2ebb9b7c0cfa24bd319fb5a65eb8babfd6c8f75b Mon Sep 17 00:00:00 2001 From: 12rambau Date: Mon, 21 Nov 2022 20:35:47 +0000 Subject: [PATCH 3/6] docs: avoid deprecation warnings --- docs/source/widgets/btn.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/widgets/btn.rst b/docs/source/widgets/btn.rst index 949d5468..91d92967 100644 --- a/docs/source/widgets/btn.rst +++ b/docs/source/widgets/btn.rst @@ -20,8 +20,8 @@ The default color is set to "primary". v.theme.dark = False btn = sw.Btn( - text = "The One btn", - icon = "fas fa-cogs" + msg = "The One btn", + gliph = "fas fa-cogs" ) btn @@ -42,8 +42,8 @@ Btn can be used to launch function on any Javascript event such as "click". v.theme.dark = False btn = sw.Btn( - text = "The One btn", - icon = "fas fa-cogs" + msg = "The One btn", + gliph = "fas fa-cogs" ) btn.on_event('click', lambda *args: print('Hello world!')) From 669a2af2ff8190b72c281c05d0e9062ac3d8ef07 Mon Sep 17 00:00:00 2001 From: 12rambau Date: Mon, 21 Nov 2022 22:12:32 +0000 Subject: [PATCH 4/6] refactor: rename parameters in the reclassify module --- sepal_ui/reclassify/reclassify_view.py | 10 ++++++---- sepal_ui/reclassify/table_view.py | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/sepal_ui/reclassify/reclassify_view.py b/sepal_ui/reclassify/reclassify_view.py index f4d6ca40..605b7819 100644 --- a/sepal_ui/reclassify/reclassify_view.py +++ b/sepal_ui/reclassify/reclassify_view.py @@ -490,18 +490,20 @@ def __init__( self.save_dialog = SaveMatrixDialog(folder=out_path) self.import_dialog = ImportMatrixDialog(folder=out_path) self.get_table = sw.Btn( - ms.rec.rec.input.btn, "far fa-table", color="success", small=True + ms.rec.rec.input.btn, gliph="far fa-table", color="success", small=True ) self.import_table = sw.Btn( "import", - "fas fa-download", + gliph="fas fa-download", color="secondary", small=True, class_="ml-2 mr-2", ) - self.save_table = sw.Btn("save", "fas fa-save", color="secondary", small=True) + self.save_table = sw.Btn( + "save", gliph="fas fa-save", color="secondary", small=True + ) self.reclassify_btn = sw.Btn( - ms.rec.rec.btn, "fas fa-chess-board", small=True, disabled=True + ms.rec.rec.btn, gliph="fas fa-chess-board", small=True, disabled=True ) self.toolbar = v.Toolbar( diff --git a/sepal_ui/reclassify/table_view.py b/sepal_ui/reclassify/table_view.py index c3f8a35a..e7b043e3 100644 --- a/sepal_ui/reclassify/table_view.py +++ b/sepal_ui/reclassify/table_view.py @@ -50,18 +50,18 @@ def __init__(self, out_path=Path.home() / "downloads", **kwargs): # and set them in the top slot of the table self.edit_btn = sw.Btn( ms.rec.table.btn.edit, - icon="fas fa-pencil-alt", + gliph="fas fa-pencil-alt", class_="ml-2 mr-2", color="secondary", small=True, ) self.delete_btn = sw.Btn( - ms.rec.table.btn.delete, icon="fas fa-trash-alt", color="error", small=True + ms.rec.table.btn.delete, gliph="fas fa-trash-alt", color="error", small=True ) self.add_btn = sw.Btn( - ms.rec.table.btn.add, icon="fas fa-plus", color="success", small=True + ms.rec.table.btn.add, gliph="fas fa-plus", color="success", small=True ) - self.save_btn = sw.Btn(ms.rec.table.btn.save, icon="far fa-save", small=True) + self.save_btn = sw.Btn(ms.rec.table.btn.save, gliph="far fa-save", small=True) slot = v.Toolbar( class_="d-flex mb-6", @@ -601,7 +601,7 @@ def __init__( ) self.btn = sw.Btn( ms.rec.table.classif.btn, - icon="far fa-table", + gliph="far fa-table", color="success", outlined=True, ) From a91cc6fe363769aef578351fe02e0ef76a512252 Mon Sep 17 00:00:00 2001 From: 12rambau Date: Mon, 21 Nov 2022 22:56:37 +0000 Subject: [PATCH 5/6] refactor: fileInput was using icon and text --- sepal_ui/reclassify/reclassify_view.py | 20 +++++++++--------- sepal_ui/reclassify/table_view.py | 28 +++++++++++++++----------- sepal_ui/sepalwidgets/inputs.py | 2 +- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/sepal_ui/reclassify/reclassify_view.py b/sepal_ui/reclassify/reclassify_view.py index 605b7819..18a90455 100644 --- a/sepal_ui/reclassify/reclassify_view.py +++ b/sepal_ui/reclassify/reclassify_view.py @@ -33,8 +33,8 @@ def __init__(self, folder, **kwargs): # create the 3 widgets title = v.CardTitle(children=["Load reclassification matrix"]) self.w_file = sw.FileInput(label="filename", folder=folder) - self.load_btn = sw.Btn("Load") - cancel = sw.Btn("Cancel", outlined=True) + self.load_btn = sw.Btn(msg="Load") + cancel = sw.Btn(msg="Cancel", outlined=True) actions = v.CardActions(children=[cancel, self.load_btn]) # default params @@ -81,8 +81,8 @@ def __init__(self, folder=Path.home(), **kwargs): # create the widgets title = v.CardTitle(children=["Save matrix"]) self.w_file = v.TextField(label="filename", v_model=None) - btn = sw.Btn("Save matrix") - cancel = sw.Btn("Cancel", outlined=True) + btn = sw.Btn(msg="Save matrix") + cancel = sw.Btn(msg="Cancel", outlined=True) actions = v.CardActions(children=[cancel, btn]) self.alert = sw.Alert(children=["Choose a name for the output"]).show() @@ -464,7 +464,7 @@ def __init__( self.btn_list = [ sw.Btn( - "Custom", + msg="Custom", _metadata={"path": "custom"}, small=True, class_="mr-2", @@ -472,7 +472,7 @@ def __init__( ) ] + [ sw.Btn( - f"use {name}", + msg=f"use {name}", _metadata={"path": path}, small=True, class_="mr-2", @@ -490,20 +490,20 @@ def __init__( self.save_dialog = SaveMatrixDialog(folder=out_path) self.import_dialog = ImportMatrixDialog(folder=out_path) self.get_table = sw.Btn( - ms.rec.rec.input.btn, gliph="far fa-table", color="success", small=True + msg=ms.rec.rec.input.btn, gliph="far fa-table", color="success", small=True ) self.import_table = sw.Btn( - "import", + msg="import", gliph="fas fa-download", color="secondary", small=True, class_="ml-2 mr-2", ) self.save_table = sw.Btn( - "save", gliph="fas fa-save", color="secondary", small=True + msg="save", gliph="fas fa-save", color="secondary", small=True ) self.reclassify_btn = sw.Btn( - ms.rec.rec.btn, gliph="fas fa-chess-board", small=True, disabled=True + msg=ms.rec.rec.btn, gliph="fas fa-chess-board", small=True, disabled=True ) self.toolbar = v.Toolbar( diff --git a/sepal_ui/reclassify/table_view.py b/sepal_ui/reclassify/table_view.py index e7b043e3..24ac31b5 100644 --- a/sepal_ui/reclassify/table_view.py +++ b/sepal_ui/reclassify/table_view.py @@ -49,19 +49,24 @@ def __init__(self, out_path=Path.home() / "downloads", **kwargs): # create the 4 CRUD btn # and set them in the top slot of the table self.edit_btn = sw.Btn( - ms.rec.table.btn.edit, + msg=ms.rec.table.btn.edit, gliph="fas fa-pencil-alt", class_="ml-2 mr-2", color="secondary", small=True, ) self.delete_btn = sw.Btn( - ms.rec.table.btn.delete, gliph="fas fa-trash-alt", color="error", small=True + msg=ms.rec.table.btn.delete, + gliph="fas fa-trash-alt", + color="error", + small=True, ) self.add_btn = sw.Btn( - ms.rec.table.btn.add, gliph="fas fa-plus", color="success", small=True + msg=ms.rec.table.btn.add, gliph="fas fa-plus", color="success", small=True + ) + self.save_btn = sw.Btn( + msg=ms.rec.table.btn.save, gliph="far fa-save", small=True ) - self.save_btn = sw.Btn(ms.rec.table.btn.save, gliph="far fa-save", small=True) slot = v.Toolbar( class_="d-flex mb-6", @@ -212,20 +217,19 @@ def __init__(self, table, **kwargs): self.title = v.CardTitle(children=[self.TITLES[0]]) # Action buttons - self.save = sw.Btn(ms.rec.table.edit_dialog.btn.save.name) + self.save = sw.Btn(msg=ms.rec.table.edit_dialog.btn.save.name) save_tool = sw.Tooltip( self.save, ms.rec.table.edit_dialog.btn.save.tooltip, bottom=True ) - self.modify = sw.Btn( - ms.rec.table.edit_dialog.btn.modify.name - ).hide() # by default modify is hidden + self.modify = sw.Btn(msg=ms.rec.table.edit_dialog.btn.modify.name) + self.modify.hide() # by default modify is hidden modify_tool = sw.Tooltip( self.modify, ms.rec.table.edit_dialog.btn.modify.tooltip, bottom=True ) self.cancel = sw.Btn( - ms.rec.table.edit_dialog.btn.cancel.name, outlined=True, class_="ml-2" + msg=ms.rec.table.edit_dialog.btn.cancel.name, outlined=True, class_="ml-2" ) cancel_tool = sw.Tooltip( self.cancel, ms.rec.table.edit_dialog.btn.cancel.tooltip, bottom=True @@ -437,7 +441,7 @@ def __init__(self, table, out_path, **kwargs): v_model=ms.rec.table.save_dialog.placeholder, ) - self.save = sw.Btn(ms.rec.table.save_dialog.btn.save.name) + self.save = sw.Btn(msg=ms.rec.table.save_dialog.btn.save.name) save = sw.Tooltip( self.save, ms.rec.table.save_dialog.btn.save.tooltip, @@ -446,7 +450,7 @@ def __init__(self, table, out_path, **kwargs): ) self.cancel = sw.Btn( - ms.rec.table.save_dialog.btn.cancel.name, outlined=True, class_="ml-2" + msg=ms.rec.table.save_dialog.btn.cancel.name, outlined=True, class_="ml-2" ) cancel = sw.Tooltip( self.cancel, ms.rec.table.save_dialog.btn.cancel.tooltip, bottom=True @@ -600,7 +604,7 @@ def __init__( folder=self.class_path, ) self.btn = sw.Btn( - ms.rec.table.classif.btn, + msg=ms.rec.table.classif.btn, gliph="far fa-table", color="success", outlined=True, diff --git a/sepal_ui/sepalwidgets/inputs.py b/sepal_ui/sepalwidgets/inputs.py index 6293f828..72990287 100644 --- a/sepal_ui/sepalwidgets/inputs.py +++ b/sepal_ui/sepalwidgets/inputs.py @@ -256,7 +256,7 @@ def __init__( "name": "activator", "variable": "x", "children": Btn( - icon="fas fa-search", v_model=False, v_on="x.on", text=label + gliph="fas fa-search", v_model=False, v_on="x.on", msg=label ), } ], From 9a39fa1b468f9c66759d57cafec31e1df0996c7d Mon Sep 17 00:00:00 2001 From: 12rambau Date: Mon, 21 Nov 2022 23:36:50 +0000 Subject: [PATCH 6/6] test: complete Btn coverage --- sepal_ui/sepalwidgets/btn.py | 9 +++++++-- tests/test_Btn.py | 13 +++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/sepal_ui/sepalwidgets/btn.py b/sepal_ui/sepalwidgets/btn.py index 183a943c..137622fa 100644 --- a/sepal_ui/sepalwidgets/btn.py +++ b/sepal_ui/sepalwidgets/btn.py @@ -43,11 +43,16 @@ def __init__(self, msg="Click", gliph="", **kwargs): if "text" in kwargs: if isinstance(kwargs["text"], str): msg = kwargs.pop("text") - warnings.warn('"text" is deprecated, please use "msg" instead') + warnings.warn( + '"text" is deprecated, please use "msg" instead', DeprecationWarning + ) if "icon" in kwargs: if isinstance(kwargs["icon"], str): gliph = kwargs.pop("icon") - warnings.warn('"icon" is deprecated, please use "gliph" instead') + warnings.warn( + '"icon" is deprecated, please use "gliph" instead', + DeprecationWarning, + ) # create the default v_icon self.v_icon = v.Icon(left=True, children=[""]) diff --git a/tests/test_Btn.py b/tests/test_Btn.py index 7f7b612c..058cb775 100644 --- a/tests/test_Btn.py +++ b/tests/test_Btn.py @@ -64,6 +64,15 @@ def test_set_gliph(self, btn): btn.gliph = gliph assert btn.v_icon.children[0] == gliph + # remove all gliph + gliph = "" + btn.gliph = gliph + assert "d-none" in btn.v_icon.class_ + + # assert deprecation + with pytest.deprecated_call(): + sw.Btn(icon="fas fa-folder") + return def test_test_msg(self, btn): @@ -76,6 +85,10 @@ def test_test_msg(self, btn): btn.msg = msg assert btn.children[1] == msg + # test deprecation notice + with pytest.deprecated_call(): + sw.Btn(text="Deprecation") + return @pytest.fixture