From 6aef9e3ad3ca7596c91ba0e8aa70a31fa0580b32 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 19:30:09 -0500 Subject: [PATCH 01/21] Variable Explorer: Don't show empty editors when the value obtained from the kernel is None --- spyder/widgets/variableexplorer/collectionseditor.py | 2 ++ spyder/widgets/variableexplorer/namespacebrowser.py | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 2946f076325..ebdb97c8cd2 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -413,6 +413,8 @@ def createEditor(self, parent, option, index): return None try: value = self.get_value(index) + if value is None: + return None except Exception as msg: QMessageBox.critical(self.parent(), _("Error"), _("Spyder was unable to retrieve the value of " diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 157a8234dea..64ea844e054 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -339,12 +339,6 @@ def get_value(self, name): self.shellwidget._kernel_value = None else: value = monitor_get_global(self._get_sock(), name) - if value is None: - if communicate(self._get_sock(), '%s is not None' % name): - import pickle - msg = to_text_string(_("Object %s is not picklable") - % name) - raise pickle.PicklingError(msg) return value def set_value(self, name, value): From 73e96ecfbac6df1fc10c00f627d12b026e2dddb3 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 19:37:53 -0500 Subject: [PATCH 02/21] IPython Console: Add more excluded names from the Variable Explorer --- spyder/utils/ipython/spyder_kernel.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/spyder/utils/ipython/spyder_kernel.py b/spyder/utils/ipython/spyder_kernel.py index bbd49712048..f4c4711b82d 100644 --- a/spyder/utils/ipython/spyder_kernel.py +++ b/spyder/utils/ipython/spyder_kernel.py @@ -50,6 +50,11 @@ ipykernel.pickleutil.can_map.pop('numpy.ndarray') +# Excluded variables from the Variable Explorer (i.e. they are not +# shown at all there) +EXCLUDED_NAMES = ['In', 'Out', 'exit', 'get_ipython', 'quit'] + + class SpyderKernel(IPythonKernel): """Spyder kernel for Jupyter""" @@ -96,8 +101,7 @@ def get_namespace_view(self): settings = self.namespace_view_settings if settings: ns = self._get_current_namespace() - more_excluded_names = ['In', 'Out'] - view = make_remote_view(ns, settings, more_excluded_names) + view = make_remote_view(ns, settings, EXCLUDED_NAMES) return view def get_var_properties(self): @@ -109,7 +113,7 @@ def get_var_properties(self): if settings: ns = self._get_current_namespace() data = get_remote_data(ns, settings, mode='editable', - more_excluded_names=['In', 'Out']) + more_excluded_names=EXCLUDED_NAMES) properties = {} for name, value in list(data.items()): @@ -180,7 +184,7 @@ def save_namespace(self, filename): ns = self._get_current_namespace() settings = self.namespace_view_settings data = get_remote_data(ns, settings, mode='picklable', - more_excluded_names=['In', 'Out']).copy() + more_excluded_names=EXCLUDED_NAMES).copy() return iofunctions.save(data, filename) # --- For Pdb From 8567308789464ad974cdf6912761076557868ef7 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 20:53:37 -0500 Subject: [PATCH 03/21] Variable Explorer: Improve how arbitrary objects are shown --- .../variableexplorer/collectionseditor.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index ebdb97c8cd2..d3964801192 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -104,9 +104,21 @@ def get_data(self): """Return model data""" return self._data + def get_data_type(self, data): + """Return data type""" + data_type = to_text_string(type(data)) + # String representations of type(foo) are of the form + # "" + # so the code below gives us + # "datetime.timedelta" + # which is exactly what we want + data_type = data_type.split()[-1][1:-2] + return data_type + def set_data(self, data, coll_filter=None): """Set model data""" self._data = data + data_type = self.get_data_type(data) if coll_filter is not None and not self.remote and \ isinstance(data, (tuple, list, dict)): @@ -128,13 +140,15 @@ def set_data(self, data, coll_filter=None): if not self.names: self.header0 = _("Key") else: - self.keys = dir(data) + self.keys = [k for k in dir(data) if not k.startswith('__')] self._data = data = self.showndata = ProxyObject(data) - self.title += _("Object") if not self.names: self.header0 = _("Attribute") - self.title += ' ('+str(len(self.keys))+' '+ _("elements")+')' + if not isinstance(self._data, ProxyObject): + self.title += ' ('+str(len(self.keys))+' '+ _("elements")+')' + else: + self.title += data_type self.total_rows = len(self.keys) if self.total_rows > LARGE_NROWS: From f81eaaddc0f42be77b5592c19d86b4ad4963351f Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:02:10 -0500 Subject: [PATCH 04/21] Variable Explorer: Fix an error when trying to change values of read only attrs --- spyder/widgets/variableexplorer/collectionseditor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index d3964801192..c36a4f55250 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -73,7 +73,10 @@ def __getitem__(self, key): return getattr(self.__obj__, key) def __setitem__(self, key, value): - setattr(self.__obj__, key, value) + try: + setattr(self.__obj__, key, value) + except TypeError: + pass class ReadOnlyCollectionsModel(QAbstractTableModel): From 3dd3310b4313534c3980a263c7cd6493a76528aa Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:15:44 -0500 Subject: [PATCH 05/21] Variable Explorer: Fix default size of CollectionsEditor dialog --- spyder/widgets/variableexplorer/collectionseditor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index c36a4f55250..f13b566c24e 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -1271,7 +1271,7 @@ def __init__(self, parent=None): self.data_copy = None self.widget = None - def setup(self, data, title='', readonly=False, width=500, remote=False, + def setup(self, data, title='', readonly=False, width=650, remote=False, icon=None, parent=None): if isinstance(data, dict): # dictionnary @@ -1306,7 +1306,7 @@ def setup(self, data, title='', readonly=False, width=500, remote=False, constant = 121 row_height = 30 error_margin = 20 - height = constant + row_height*min([15, datalen]) + error_margin + height = constant + row_height*min([10, datalen]) + error_margin self.resize(width, height) self.setWindowTitle(self.widget.get_title()) From 97b741675b5f7bb75dca216cdb60c4da0c35a5cc Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:26:54 -0500 Subject: [PATCH 06/21] Variable Explorer: Show object attrs if all of them are hidden --- spyder/widgets/variableexplorer/collectionseditor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index f13b566c24e..a9390b9f9ea 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -143,7 +143,10 @@ def set_data(self, data, coll_filter=None): if not self.names: self.header0 = _("Key") else: - self.keys = [k for k in dir(data) if not k.startswith('__')] + keys = [k for k in dir(data) if not k.startswith('__')] + if not keys: + keys = dir(data) + self.keys = keys self._data = data = self.showndata = ProxyObject(data) if not self.names: self.header0 = _("Attribute") From 2cabdfe20973e2eee544834e8894ad94563eb988 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:38:46 -0500 Subject: [PATCH 07/21] Variable Explorer: Add a new function called get_object_attrs in collectionseditor.py - We use this function instead of dir. - It's the result of dir(obj) but with the protected methods of obj filtered. --- .../variableexplorer/collectionseditor.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index a9390b9f9ea..a645a5f1026 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -61,13 +61,25 @@ LARGE_NROWS = 100 +def get_object_attrs(obj): + """ + Get the attributes of an object using dir. + + This filters protected attributes + """ + attrs = [k for k in dir(obj) if not k.startswith('__')] + if not attrs: + attrs = dir(obj) + return attrs + + class ProxyObject(object): """Dictionary proxy to an unknown object""" def __init__(self, obj): self.__obj__ = obj def __len__(self): - return len(dir(self.__obj__)) + return len(get_object_attrs(self.__obj__)) def __getitem__(self, key): return getattr(self.__obj__, key) @@ -143,10 +155,7 @@ def set_data(self, data, coll_filter=None): if not self.names: self.header0 = _("Key") else: - keys = [k for k in dir(data) if not k.startswith('__')] - if not keys: - keys = dir(data) - self.keys = keys + self.keys = get_object_attrs(data) self._data = data = self.showndata = ProxyObject(data) if not self.names: self.header0 = _("Attribute") @@ -1288,7 +1297,7 @@ def setup(self, data, title='', readonly=False, width=650, remote=False, # unknown object import copy self.data_copy = copy.deepcopy(data) - datalen = len(dir(data)) + datalen = len(get_object_attrs(data)) self.widget = CollectionsEditorWidget(self, self.data_copy, title=title, readonly=readonly, remote=remote) From 34afb056d4ef333c3d7e0aeadb895e0b5ce2158f Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:41:10 -0500 Subject: [PATCH 08/21] Variable Explorer: Improve size of CollectionsEditor dialog a bit --- spyder/widgets/variableexplorer/collectionseditor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index a645a5f1026..5c1a28f6fff 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -1317,7 +1317,7 @@ def setup(self, data, title='', readonly=False, width=650, remote=False, constant = 121 row_height = 30 - error_margin = 20 + error_margin = 10 height = constant + row_height*min([10, datalen]) + error_margin self.resize(width, height) From 2315bff8ed9b99eb2485c432d9e8604ff15383ec Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 21:48:35 -0500 Subject: [PATCH 09/21] Variable Explorer: Show empty arrays and images --- spyder/widgets/variableexplorer/arrayeditor.py | 6 ++---- spyder/widgets/variableexplorer/collectionseditor.py | 6 +----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/spyder/widgets/variableexplorer/arrayeditor.py b/spyder/widgets/variableexplorer/arrayeditor.py index 1e9da664677..577630e36d9 100644 --- a/spyder/widgets/variableexplorer/arrayeditor.py +++ b/spyder/widgets/variableexplorer/arrayeditor.py @@ -158,7 +158,7 @@ def __init__(self, data, format="%.3f", xlabels=None, ylabels=None, self.hue0 = huerange[0] self.dhue = huerange[1]-huerange[0] self.bgcolor_enabled = True - except TypeError: + except (TypeError, ValueError): self.vmin = None self.vmax = None self.hue0 = None @@ -605,9 +605,7 @@ def setup_and_check(self, data, title='', readonly=False, self.data.flags.writeable = True is_record_array = data.dtype.names is not None is_masked_array = isinstance(data, np.ma.MaskedArray) - if data.size == 0: - self.error(_("Array is empty")) - return False + if data.ndim > 3: self.error(_("Arrays with more than 3 dimensions are not supported")) return False diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 5c1a28f6fff..688021a8b91 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -466,8 +466,6 @@ def createEditor(self, parent, option, index): #---editor = ArrayEditor elif isinstance(value, (ndarray, MaskedArray)) \ and ndarray is not FakeObject: - if value.size == 0: - return None editor = ArrayEditor(parent) if not editor.setup_and_check(value, title=key, readonly=readonly): return @@ -478,8 +476,6 @@ def createEditor(self, parent, option, index): elif isinstance(value, Image) and ndarray is not FakeObject \ and Image is not FakeObject: arr = array(value) - if arr.size == 0: - return None editor = ArrayEditor(parent) if not editor.setup_and_check(arr, title=key, readonly=readonly): return @@ -510,7 +506,7 @@ def createEditor(self, parent, option, index): editor.setFont(get_font(font_size_delta=DEFAULT_SMALL_DELTA)) return editor #---editor = TextEditor - elif is_text_string(value) and len(value)>40: + elif is_text_string(value) and len(value) > 40: editor = TextEditor(value, key) self.create_dialog(editor, dict(model=index.model(), editor=editor, key=key, readonly=readonly)) From 490cf5dc4633047f6d415c0a85d6787df8311e30 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Thu, 10 Nov 2016 22:13:29 -0500 Subject: [PATCH 10/21] Variable Explorer: Rezise rows to their contents --- spyder/widgets/variableexplorer/namespacebrowser.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 64ea844e054..31a4140b803 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -319,6 +319,10 @@ def refresh_table(self): except socket.error: # Process was terminated before calling this method pass + try: + self.editor.resizeRowToContents() + except TypeError: + pass def process_remote_view(self, remote_view): """Process remote view""" From 672d66eabf4cc5e27c4e47c8307c4115191565c3 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 19 Dec 2016 11:28:08 -0500 Subject: [PATCH 11/21] Variable Explorer: Avoid error because of no execution_count --- spyder/widgets/ipythonconsole/namespacebrowser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spyder/widgets/ipythonconsole/namespacebrowser.py b/spyder/widgets/ipythonconsole/namespacebrowser.py index a4a6b613c8b..f5eec1a07db 100644 --- a/spyder/widgets/ipythonconsole/namespacebrowser.py +++ b/spyder/widgets/ipythonconsole/namespacebrowser.py @@ -177,7 +177,7 @@ def _handle_execute_reply(self, msg): self._reading = False # Refresh namespacebrowser after the kernel starts running - exec_count = msg['content']['execution_count'] + exec_count = msg['content'].get('execution_count', '') if exec_count == 0 and self._kernel_is_starting: if self.namespacebrowser is not None: self.set_namespace_view_settings() From d7b85d1c455d284f0e7bcb0ac3c36ab8cc9ed2a8 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 19 Dec 2016 11:39:41 -0500 Subject: [PATCH 12/21] Fix style issues --- spyder/widgets/variableexplorer/collectionseditor.py | 8 +++++--- spyder/widgets/variableexplorer/namespacebrowser.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 8c12f6d0751..b01d266267e 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -74,7 +74,7 @@ def get_object_attrs(obj): class ProxyObject(object): - """Dictionary proxy to an unknown object""" + """Dictionary proxy to an unknown object.""" def __init__(self, obj): self.__obj__ = obj @@ -162,7 +162,8 @@ def set_data(self, data, coll_filter=None): self.header0 = _("Attribute") if not isinstance(self._data, ProxyObject): - self.title += ' ('+str(len(self.keys))+' '+ _("elements")+')' + self.title += (' (' + str(len(self.keys)) + ' ' + + _("elements") + ')') else: self.title += data_type @@ -1306,6 +1307,7 @@ def __init__(self, parent=None): def setup(self, data, title='', readonly=False, width=650, remote=False, icon=None, parent=None): + """Setup editor.""" if isinstance(data, dict): # dictionnary self.data_copy = data.copy() @@ -1339,7 +1341,7 @@ def setup(self, data, title='', readonly=False, width=650, remote=False, constant = 121 row_height = 30 error_margin = 10 - height = constant + row_height*min([10, datalen]) + error_margin + height = constant + row_height * min([10, datalen]) + error_margin self.resize(width, height) self.setWindowTitle(self.widget.get_title()) diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index e74576d1fcd..6710ca0d76a 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -356,8 +356,9 @@ def get_value(self, name): else: value = monitor_get_global(self._get_sock(), name) return value - + def set_value(self, name, value): + """Set value for a variable""" if self.is_ipyclient: value = serialize_object(value) self.shellwidget.set_value(name, value) From 470d3aa242e911ffefc8cfbad33ea07d81697bf8 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Mon, 19 Dec 2016 11:44:28 -0500 Subject: [PATCH 13/21] More style fixes --- spyder/widgets/variableexplorer/arrayeditor.py | 3 ++- spyder/widgets/variableexplorer/collectionseditor.py | 1 + spyder/widgets/variableexplorer/namespacebrowser.py | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/spyder/widgets/variableexplorer/arrayeditor.py b/spyder/widgets/variableexplorer/arrayeditor.py index 0765feb107d..8492b606fa9 100644 --- a/spyder/widgets/variableexplorer/arrayeditor.py +++ b/spyder/widgets/variableexplorer/arrayeditor.py @@ -608,7 +608,8 @@ def setup_and_check(self, data, title='', readonly=False, is_masked_array = isinstance(data, np.ma.MaskedArray) if data.ndim > 3: - self.error(_("Arrays with more than 3 dimensions are not supported")) + self.error(_("Arrays with more than 3 dimensions are not " + "supported")) return False if xlabels is not None and len(xlabels) != self.data.shape[1]: self.error(_("The 'xlabels' argument length do no match array " diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index b01d266267e..f7fe78a2d70 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -75,6 +75,7 @@ def get_object_attrs(obj): class ProxyObject(object): """Dictionary proxy to an unknown object.""" + def __init__(self, obj): self.__obj__ = obj diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 6710ca0d76a..90bf1c52c02 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -358,7 +358,7 @@ def get_value(self, name): return value def set_value(self, name, value): - """Set value for a variable""" + """Set value for a variable.""" if self.is_ipyclient: value = serialize_object(value) self.shellwidget.set_value(name, value) From 2db3ae4dcb36d6a3c831b5316a0f79f2995924c8 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 13:16:40 -0500 Subject: [PATCH 14/21] Variable Explorer: Remove the remote_editing option --- spyder/config/main.py | 5 ++--- spyder/plugins/variableexplorer.py | 12 +----------- spyder/widgets/variableexplorer/utils.py | 3 +-- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/spyder/config/main.py b/spyder/config/main.py index 5e9c75b67bc..b9c55bd95f5 100755 --- a/spyder/config/main.py +++ b/spyder/config/main.py @@ -193,8 +193,7 @@ 'exclude_capitalized': False, 'exclude_unsupported': True, 'truncate': True, - 'minmax': False, - 'remote_editing': False, + 'minmax': False }), ('editor', { @@ -656,7 +655,7 @@ # or if you want to *rename* options, then you need to do a MAJOR update in # version, e.g. from 3.0.0 to 4.0.0 # 3. You don't need to touch this value if you're just adding a new option -CONF_VERSION = '30.0.0' +CONF_VERSION = '31.0.0' # Main configuration instance try: diff --git a/spyder/plugins/variableexplorer.py b/spyder/plugins/variableexplorer.py index 7874ebd899d..41fd5e640da 100644 --- a/spyder/plugins/variableexplorer.py +++ b/spyder/plugins/variableexplorer.py @@ -14,7 +14,6 @@ from spyder.config.base import _ from spyder.plugins import SpyderPluginMixin from spyder.plugins.configdialog import PluginConfigPage -from spyder.utils import programs from spyder.utils import icon_manager as ima from spyder.widgets.variableexplorer.namespacebrowser import NamespaceBrowser from spyder.widgets.variableexplorer.utils import REMOTE_SETTINGS @@ -40,16 +39,7 @@ def setup_page(self): for option, text in filter_data] display_group = QGroupBox(_("Display")) - display_data = [] - if programs.is_module_installed('numpy'): - display_data.append(('minmax', _("Show arrays min/max"), '')) - display_data.append( - ('remote_editing', _("Edit data in the remote process"), - _("Editors are opened in the remote process for NumPy " - "arrays, PIL images, lists, tuples and dictionaries.\n" - "This avoids transfering large amount of data between " - "the remote process and Spyder (through the socket).")) - ) + display_data = [('minmax', _("Show arrays min/max"), '')] display_boxes = [self.create_checkbox(text, option, tip=tip) for option, text, tip in display_data] diff --git a/spyder/widgets/variableexplorer/utils.py b/spyder/widgets/variableexplorer/utils.py index cfd22e4d85d..b1679f87325 100644 --- a/spyder/widgets/variableexplorer/utils.py +++ b/spyder/widgets/variableexplorer/utils.py @@ -450,8 +450,7 @@ def globalsfilter(input_dict, check_all=False, filters=None, #============================================================================== REMOTE_SETTINGS = ('check_all', 'exclude_private', 'exclude_uppercase', 'exclude_capitalized', 'exclude_unsupported', - 'excluded_names', 'minmax', 'remote_editing', - 'autorefresh') + 'excluded_names', 'minmax', 'autorefresh') def get_remote_data(data, settings, mode, more_excluded_names=None): From ed36002e1cb53bb49910a5d47bc2c5ae54a952f5 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 13:26:08 -0500 Subject: [PATCH 15/21] Variable Explorer: Remove code related to remote editing --- .../variableexplorer/collectionseditor.py | 34 +------------------ .../variableexplorer/namespacebrowser.py | 5 +-- 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index f7fe78a2d70..5fe614c7e70 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -1396,11 +1396,9 @@ def __init__(self, parent, data, minmax=False, get_array_shape_func=None, get_array_ndim_func=None, oedit_func=None, plot_func=None, imshow_func=None, is_data_frame_func=None, is_series_func=None, - show_image_func=None, remote_editing=False): + show_image_func=None): BaseTableView.__init__(self, parent) - self.remote_editing_enabled = None - self.remove_values = remove_values_func self.copy_value = copy_value_func self.new_value = new_value_func @@ -1440,36 +1438,6 @@ def setup_menu(self, minmax): menu = BaseTableView.setup_menu(self, minmax) return menu - def oedit_possible(self, key): - if (self.is_list(key) or self.is_dict(key) - or self.is_array(key) or self.is_image(key) - or self.is_data_frame(key) or self.is_series(key)): - # If this is a remote dict editor, the following avoid - # transfering large amount of data through the socket - return True - - def edit_item(self): - """ - Reimplement BaseTableView's method to edit item - - Some supported data types are directly edited in the remote process, - thus avoiding to transfer large amount of data through the socket from - the remote process to Spyder - """ - if self.remote_editing_enabled: - index = self.currentIndex() - if not index.isValid(): - return - key = self.model.get_key(index) - if self.oedit_possible(key): - # If this is a remote dict editor, the following avoid - # transfering large amount of data through the socket - self.oedit(key) - else: - BaseTableView.edit_item(self) - else: - BaseTableView.edit_item(self) - #============================================================================== # Tests diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 90bf1c52c02..99f977ebf05 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -80,7 +80,6 @@ def __init__(self, parent): self.exclude_unsupported = None self.excluded_names = None self.minmax = None - self.remote_editing = None self.autorefresh = None # Other setting @@ -102,7 +101,7 @@ def setup(self, check_all=None, exclude_private=None, exclude_uppercase=None, exclude_capitalized=None, exclude_unsupported=None, excluded_names=None, minmax=None, dataframe_format=None, - remote_editing=None, autorefresh=None): + autorefresh=None): """ Setup the namespace browser with provided settings. @@ -119,7 +118,6 @@ def setup(self, check_all=None, exclude_private=None, self.exclude_unsupported = exclude_unsupported self.excluded_names = excluded_names self.minmax = minmax - self.remote_editing = remote_editing self.autorefresh = autorefresh self.dataframe_format = dataframe_format @@ -138,7 +136,6 @@ def setup(self, check_all=None, exclude_private=None, self.editor = RemoteCollectionsEditorTableView(self, None, minmax=minmax, dataframe_format=dataframe_format, - remote_editing=remote_editing, get_value_func=self.get_value, set_value_func=self.set_value, new_value_func=self.set_value, From 56e3a5adb48f061e15e64e48dbcd3a66ae4d9b38 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 13:39:35 -0500 Subject: [PATCH 16/21] Variable Explorer: Remove more code related to remote editing --- spyder/widgets/variableexplorer/collectionseditor.py | 3 +-- spyder/widgets/variableexplorer/namespacebrowser.py | 6 ------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 5fe614c7e70..bb0dc6f1b9f 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -1394,7 +1394,7 @@ def __init__(self, parent, data, minmax=False, copy_value_func=None, is_list_func=None, get_len_func=None, is_array_func=None, is_image_func=None, is_dict_func=None, get_array_shape_func=None, get_array_ndim_func=None, - oedit_func=None, plot_func=None, imshow_func=None, + plot_func=None, imshow_func=None, is_data_frame_func=None, is_series_func=None, show_image_func=None): BaseTableView.__init__(self, parent) @@ -1412,7 +1412,6 @@ def __init__(self, parent, data, minmax=False, self.is_dict = is_dict_func self.get_array_shape = get_array_shape_func self.get_array_ndim = get_array_ndim_func - self.oedit = oedit_func self.plot = plot_func self.imshow = imshow_func self.show_image = show_image_func diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 99f977ebf05..7f57ea73e39 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -150,7 +150,6 @@ def setup(self, check_all=None, exclude_private=None, is_series_func=self.is_series, get_array_shape_func=self.get_array_shape, get_array_ndim_func=self.get_array_ndim, - oedit_func=self.oedit, plot_func=self.plot, imshow_func=self.imshow, show_image_func=self.show_image) self.editor.sig_option_changed.connect(self.sig_option_changed.emit) @@ -472,11 +471,6 @@ def show_image(self, name): else: self.shellwidget.send_to_process(command) - def oedit(self, name): - command = "from spyder.widgets.variableexplorer.objecteditor import oedit; " \ - "oedit('%s', modal=False, namespace=locals());" % name - self.shellwidget.send_to_process(command) - #------ Set, load and save data ------------------------------------------- def set_data(self, data): """Set data""" From e201ebc03dadf73396aee3613dedbbb9095d79ff Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 14:41:44 -0500 Subject: [PATCH 17/21] Fix style issues --- spyder/config/main.py | 2 +- spyder/plugins/variableexplorer.py | 4 ++-- .../widgets/variableexplorer/collectionseditor.py | 9 ++++++--- spyder/widgets/variableexplorer/namespacebrowser.py | 13 ++++++++----- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/spyder/config/main.py b/spyder/config/main.py index b9c55bd95f5..cb6a6a50cbd 100755 --- a/spyder/config/main.py +++ b/spyder/config/main.py @@ -194,7 +194,7 @@ 'exclude_unsupported': True, 'truncate': True, 'minmax': False - }), + }), ('editor', { 'printer_header/font/family': SANS_SERIF, diff --git a/spyder/plugins/variableexplorer.py b/spyder/plugins/variableexplorer.py index 41fd5e640da..50cb126e5dc 100644 --- a/spyder/plugins/variableexplorer.py +++ b/spyder/plugins/variableexplorer.py @@ -42,12 +42,12 @@ def setup_page(self): display_data = [('minmax', _("Show arrays min/max"), '')] display_boxes = [self.create_checkbox(text, option, tip=tip) for option, text, tip in display_data] - + ar_layout = QVBoxLayout() ar_layout.addWidget(ar_box) ar_layout.addWidget(ar_spin) ar_group.setLayout(ar_layout) - + filter_layout = QVBoxLayout() for box in filter_boxes: filter_layout.addWidget(box) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index bb0dc6f1b9f..a4f2ac07b7a 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -1438,22 +1438,25 @@ def setup_menu(self, minmax): return menu -#============================================================================== +# ============================================================================= # Tests -#============================================================================== +# ============================================================================= def get_test_data(): - """Create test data""" + """Create test data.""" import numpy as np from spyder.pil_patch import Image image = Image.fromarray(np.random.random_integers(255, size=(100, 100)), mode='P') testdict = {'d': 1, 'a': np.random.rand(10, 10), 'b': [1, 2]} testdate = datetime.date(1945, 5, 8) + class Foobar(object): + def __init__(self): self.text = "toto" self.testdict = testdict self.testdate = testdate + foobar = Foobar() return {'object': foobar, 'str': 'kjkj kj k j j kj k jkj', diff --git a/spyder/widgets/variableexplorer/namespacebrowser.py b/spyder/widgets/variableexplorer/namespacebrowser.py index 7f57ea73e39..2cc1d7b669d 100644 --- a/spyder/widgets/variableexplorer/namespacebrowser.py +++ b/spyder/widgets/variableexplorer/namespacebrowser.py @@ -133,7 +133,9 @@ def setup(self, check_all=None, exclude_private=None, self.refresh_table() return - self.editor = RemoteCollectionsEditorTableView(self, None, + self.editor = RemoteCollectionsEditorTableView( + self, + None, minmax=minmax, dataframe_format=dataframe_format, get_value_func=self.get_value, @@ -152,6 +154,7 @@ def setup(self, check_all=None, exclude_private=None, get_array_ndim_func=self.get_array_ndim, plot_func=self.plot, imshow_func=self.imshow, show_image_func=self.show_image) + self.editor.sig_option_changed.connect(self.sig_option_changed.emit) self.editor.sig_files_dropped.connect(self.import_data) @@ -471,21 +474,21 @@ def show_image(self, name): else: self.shellwidget.send_to_process(command) - #------ Set, load and save data ------------------------------------------- + # ------ Set, load and save data ------------------------------------------ def set_data(self, data): - """Set data""" + """Set data.""" if data != self.editor.model.get_data(): self.editor.set_data(data) self.editor.adjust_columns() def collapse(self): - """Collapse""" + """Collapse.""" self.sig_collapse.emit() @Slot(bool) @Slot(list) def import_data(self, filenames=None): - """Import data from text file""" + """Import data from text file.""" title = _("Import data") if filenames is None: if self.filename is None: From cf64801935405fd5a113ce96ae8c394b9afb2516 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 15:52:31 -0500 Subject: [PATCH 18/21] Variable Explorer: Move get_object_attrs from collectionseditor to utils --- .../variableexplorer/collectionseditor.py | 14 +------------- spyder/widgets/variableexplorer/utils.py | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index a4f2ac07b7a..299e001071d 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -49,7 +49,7 @@ array, DataFrame, display_to_value, FakeObject, get_color_name, get_human_readable_type, get_size, Image, is_editable_type, is_known_type, MaskedArray, ndarray, np_savetxt, Series, sort_against, try_to_eval, - unsorted_unique, value_to_display,) + unsorted_unique, value_to_display, get_object_attrs) if ndarray is not FakeObject: from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor @@ -61,18 +61,6 @@ LARGE_NROWS = 100 -def get_object_attrs(obj): - """ - Get the attributes of an object using dir. - - This filters protected attributes - """ - attrs = [k for k in dir(obj) if not k.startswith('__')] - if not attrs: - attrs = dir(obj) - return attrs - - class ProxyObject(object): """Dictionary proxy to an unknown object.""" diff --git a/spyder/widgets/variableexplorer/utils.py b/spyder/widgets/variableexplorer/utils.py index b1679f87325..dfaee8d07a8 100644 --- a/spyder/widgets/variableexplorer/utils.py +++ b/spyder/widgets/variableexplorer/utils.py @@ -138,10 +138,22 @@ def get_size(item): return 1 -#============================================================================== +def get_object_attrs(obj): + """ + Get the attributes of an object using dir. + + This filters protected attributes + """ + attrs = [k for k in dir(obj) if not k.startswith('__')] + if not attrs: + attrs = dir(obj) + return attrs + + +# ============================================================================= # Set limits for the amount of elements in the repr of collections (lists, # dicts, tuples and sets) and Numpy arrays -#============================================================================== +# ============================================================================= CollectionsRepr = reprlib.Repr() CollectionsRepr.maxlist = 10 CollectionsRepr.maxdict = 10 From 642a1930acb850bb60bb38f011815513c780fa4e Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 15:56:24 -0500 Subject: [PATCH 19/21] Variable Explorer: Use get_type_string instead of my poorer get_data_type --- .../widgets/variableexplorer/collectionseditor.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 299e001071d..5459c50834c 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -49,7 +49,7 @@ array, DataFrame, display_to_value, FakeObject, get_color_name, get_human_readable_type, get_size, Image, is_editable_type, is_known_type, MaskedArray, ndarray, np_savetxt, Series, sort_against, try_to_eval, - unsorted_unique, value_to_display, get_object_attrs) + unsorted_unique, value_to_display, get_object_attrs, get_type_string) if ndarray is not FakeObject: from spyder.widgets.variableexplorer.arrayeditor import ArrayEditor @@ -109,21 +109,10 @@ def get_data(self): """Return model data""" return self._data - def get_data_type(self, data): - """Return data type""" - data_type = to_text_string(type(data)) - # String representations of type(foo) are of the form - # "" - # so the code below gives us - # "datetime.timedelta" - # which is exactly what we want - data_type = data_type.split()[-1][1:-2] - return data_type - def set_data(self, data, coll_filter=None): """Set model data""" self._data = data - data_type = self.get_data_type(data) + data_type = get_type_string(data) if coll_filter is not None and not self.remote and \ isinstance(data, (tuple, list, dict)): From 3d80c2cb13ec22fc075d127690e64d53add95b1b Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 15:59:21 -0500 Subject: [PATCH 20/21] Variable Explorer: Use to_text_string instead of str in get_type_string --- spyder/widgets/variableexplorer/utils.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spyder/widgets/variableexplorer/utils.py b/spyder/widgets/variableexplorer/utils.py index dfaee8d07a8..bd95fb7aa84 100644 --- a/spyder/widgets/variableexplorer/utils.py +++ b/spyder/widgets/variableexplorer/utils.py @@ -374,16 +374,17 @@ def display_to_value(value, default_value, ignore_errors=True): return value -#============================================================================== +# ============================================================================= # Types -#============================================================================== +# ============================================================================= def get_type_string(item): - """Return type string of an object""" + """Return type string of an object.""" if isinstance(item, DataFrame): return "DataFrame" if isinstance(item, Series): return "Series" - found = re.findall(r"<(?:type|class) '(\S*)'>", str(type(item))) + found = re.findall(r"<(?:type|class) '(\S*)'>", + to_text_string(type(item))) if found: return found[0] From a540f41805e1eb0372eec5732add0afc54f5c1d2 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Wed, 28 Dec 2016 16:06:02 -0500 Subject: [PATCH 21/21] Variable Explorer: Add missing docstrings --- spyder/widgets/variableexplorer/collectionseditor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spyder/widgets/variableexplorer/collectionseditor.py b/spyder/widgets/variableexplorer/collectionseditor.py index 5459c50834c..907a27eb971 100644 --- a/spyder/widgets/variableexplorer/collectionseditor.py +++ b/spyder/widgets/variableexplorer/collectionseditor.py @@ -65,15 +65,19 @@ class ProxyObject(object): """Dictionary proxy to an unknown object.""" def __init__(self, obj): + """Constructor.""" self.__obj__ = obj def __len__(self): + """Get len according to detected attributes.""" return len(get_object_attrs(self.__obj__)) def __getitem__(self, key): + """Get attribute corresponding to key.""" return getattr(self.__obj__, key) def __setitem__(self, key, value): + """Set attribute corresponding to key with value.""" try: setattr(self.__obj__, key, value) except TypeError: