@@ -98,7 +98,7 @@
Loading
98 98
    name = param.String(default='', doc="""
99 99
        Title of the pane.""")
100 100
101 -
    parameters = param.List(default=[], doc="""
101 +
    parameters = param.List(default=[], allow_None=True, doc="""
102 102
        If set this serves as a whitelist of parameters to display on
103 103
        the supplied Parameterized object.""")
104 104
@@ -154,8 +154,13 @@
Loading
154 154
            object = object.owner
155 155
        if isinstance(object, param.parameterized.Parameters):
156 156
            object = object.cls if object.self is None else object.self
157 +
157 158
        if 'parameters' not in params and object is not None:
158 159
            params['parameters'] = [p for p in object.param if p != 'name']
160 +
            self._explicit_parameters = False
161 +
        else:
162 +
            self._explicit_parameters = object is not None
163 +
159 164
        if object and 'name' not in params:
160 165
            params['name'] = param_name(object.name)
161 166
        super(Param, self).__init__(object, **params)
@@ -216,17 +221,28 @@
Loading
216 221
        for event in sorted(events, key=lambda x: x.name):
217 222
            if event.name == 'object':
218 223
                if isinstance(event.new, param.parameterized.Parameters):
224 +
                    # Setting object will trigger this method a second time
219 225
                    self.object = event.new.cls if event.new.self is None else event.new.self
220 226
                    return
221 -
                if event.new is None:
227 +
                
228 +
                if self._explicit_parameters:
229 +
                    parameters = self.parameters
230 +
                elif event.new is None:
222 231
                    parameters = []
223 232
                else:
224 233
                    parameters = [p for p in event.new.param if p != 'name']
225 234
                    self.name = param_name(event.new.name)
226 235
            if event.name == 'parameters':
227 -
                parameters = [] if event.new == [] else event.new
236 +
                if event.new is None:
237 +
                    self._explicit_parameters = False
238 +
                    if self.object is not None:
239 +
                        parameters = [p for p in self.object.param if p != 'name']
240 +
                else:
241 +
                    self._explicit_parameters = True
242 +
                    parameters = [] if event.new == [] else event.new
228 243
229 244
        if parameters != [] and parameters != self.parameters:
245 +
            # Setting parameters will trigger this method a second time
230 246
            self.parameters = parameters
231 247
            return
232 248

@@ -1097,3 +1097,34 @@
Loading
1097 1097
1098 1098
    assert test.a == 2
1099 1099
    del os.environ['PARAM_JSON_INIT']
1100 +
1101 +
def test_change_object_and_keep_parameters():
1102 +
    """Test that https://github.com/holoviz/panel/issues/1581 is solved"""
1103 +
    # Given
1104 +
    class TextModel(param.Parameterized):
1105 +
        text = param.String()
1106 +
        param2 = param.String()
1107 +
1108 +
    class TextView(param.Parameterized):
1109 +
        text = param.ClassSelector(class_=TextModel)
1110 +
        text_pane = param.Parameter()
1111 +
1112 +
        def __init__(self, **params):
1113 +
            params["text"] = TextModel(text="Original Text")
1114 +
            super().__init__(**params)
1115 +
1116 +
            self.text_pane = Param(
1117 +
                self.text, parameters=["text"]
1118 +
            )
1119 +
1120 +
        @param.depends("text", watch=True)
1121 +
        def _update_text_pane(self, *_):
1122 +
            self.text_pane.object = self.text
1123 +
1124 +
    view = TextView()
1125 +
    assert view.text_pane.parameters==["text"]
1126 +
1127 +
    # When
1128 +
    view.text = TextModel(text="New TextModel")
1129 +
    # Then
1130 +
    assert view.text_pane.parameters==["text"]
Files Coverage
panel 86.08%
dodo.py 0.00%
setup.py 0.00%
Project Totals (147 files) 85.68%
6635.1
TRAVIS_PYTHON_VERSION=3.6
TRAVIS_OS_NAME=linux
6633.1
TRAVIS_PYTHON_VERSION=3.6
TRAVIS_OS_NAME=linux
1
coverage:
2
  status:
3
    project:
4
      default:
5
        target: auto
6
        threshold: 0.1
7
        base: auto
8

9
comment:
10
  require_changes: yes
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading