Remove blank-line whitespace in files without PR conflicts

Esse commit está contido em:
C.A.M. Gerlach
2019-05-26 12:46:50 -05:00
commit fd3a4f557a
64 arquivos alterados com 677 adições e 677 exclusões
+3 -3
Ver Arquivo
@@ -9,14 +9,14 @@ coverage:
precision: 2
round: down
range: "70...100"
status:
project:
default:
threshold: 1%
patch: no
changes: no
parsers:
gcov:
branch_detection:
@@ -24,5 +24,5 @@ parsers:
loop: yes
method: no
macro: no
comment: false
+10 -10
Ver Arquivo
@@ -37,19 +37,19 @@ ROPE_PREFS = {
def ropetest():
project = rope.base.project.Project('src', **ROPE_PREFS)
project.validate(project.root)
filename = osp.join('src', 'script.py')
source_code = file(filename, 'rb').read()
offset = len(source_code)
resource = rope.base.libutils.path_to_resource(project, filename)
t0 = time.time()
proposals = rope.contrib.codeassist.code_assist(project, source_code,
offset, resource)
proposals = rope.contrib.codeassist.sorted_proposals(proposals)
print "%s: %d ms" % ("completion", 10*round(1e2*(time.time()-t0)))
print 'loadtxt' in [proposal.name for proposal in proposals]
@@ -77,22 +77,22 @@ rope_patch.apply()
def other_features():
project = rope.base.project.Project('src', **ROPE_PREFS)
project.validate(project.root)
filename = osp.join('src', 'script2.py')
source_code = file(filename, 'rb').read()
offset = len(source_code)
resource = rope.base.libutils.path_to_resource(project, filename)
t0 = time.time()
cts = rope.contrib.codeassist.get_calltip(
project, source_code, offset, resource)
doc_text = rope.contrib.codeassist.get_doc(
project, source_code, offset, resource)
def_loc = rope.contrib.codeassist.get_definition_location(
project, source_code, offset, resource)
msg = "Testing other rope instrospection features"
print msg
print "="*len(msg)
+10 -10
Ver Arquivo
@@ -82,7 +82,7 @@ def get_tours(index=None):
def get_tour(index):
"""
This function generates a list of tours.
The index argument is used to retrieve a particular tour. If None is
passed, it will return the full list of tours. If instead -1 is given,
this function will return a test tour
@@ -171,7 +171,7 @@ def get_tour(index):
'widgets': [sw.ipython_console],
'run': ["li = list(range(100))", "d = {'a': 1, 'b': 2}"]
},
{'title': _("The Variable Explorer"),
'content': _("In this pane you can view and edit the variables "
"generated during the execution of a program, or "
@@ -449,9 +449,9 @@ class FadingCanvas(FadingDialog):
width, height = geo.width(), geo.height()
point = widget.mapTo(self.parent, QPoint(0, 0))
x, y = point.x(), point.y()
temp_path.addRect(QRectF(x, y, width, height))
temp_region = QRegion(x, y, width, height)
if self.interaction_on:
@@ -608,11 +608,11 @@ class FadingTipBox(FadingDialog):
subcontrol-position: top left;
border-width: 0px;
}}
QComboBox::down-arrow {{
image: url({});
}}
'''.format(self.combobox_background.name(), arrow)
# Windows fix, slashes should be always in unix-style
self.stylesheet = self.stylesheet.replace('\\', '/')
@@ -848,7 +848,7 @@ class AnimatedTour(QWidget):
QWidget.__init__(self, parent)
self.parent = parent
# Variables to adjust
self.duration_canvas = [666, 666]
self.duration_tips = [333, 333]
@@ -1080,13 +1080,13 @@ class AnimatedTour(QWidget):
if dockwidgets[0] is not None:
geo = dockwidgets[0].geometry()
x, y, width, height = geo.x(), geo.y(), geo.width(), geo.height()
point = dockwidgets[0].mapToGlobal(QPoint(0, 0))
x_glob, y_glob = point.x(), point.y()
# Check if is too tall and put to the side
y_fac = (height / self.height_main) * 100
if y_fac > 60: # FIXME:
if x < self.tips.width():
x = x_glob + width + delta
+4 -4
Ver Arquivo
@@ -227,7 +227,7 @@ def get_module_path(modname):
def get_module_data_path(modname, relpath=None, attr_name='DATAPATH'):
"""Return module *modname* data path
Note: relpath is ignored if module has an attribute named *attr_name*
Handles py2exe/cx_Freeze distributions"""
datapath = getattr(sys.modules[modname], attr_name, '')
if datapath:
@@ -249,10 +249,10 @@ def get_module_source_path(modname, basename=None):
"""Return module *modname* source path
If *basename* is specified, return *modname.basename* path where
*modname* is a package containing the module *basename*
*basename* is a filename (not a module name), so it must include the
file extension: .py or .pyw
Handles py2exe/cx_Freeze distributions"""
srcpath = get_module_path(modname)
parentdir = osp.join(srcpath, osp.pardir)
@@ -446,7 +446,7 @@ def get_translation(modname, dirname=None):
return translate_dumb
else:
os.environ["LANGUAGE"] = language # Works on Linux
import gettext
try:
_trans = gettext.translation(modname, locale_path, codeset="utf-8")
+1 -1
Ver Arquivo
@@ -116,7 +116,7 @@ def fixed_shortcut(keystr, parent, action):
def config_shortcut(action, context, name, parent):
"""
Create a Shortcut namedtuple for a widget
The data contained in this tuple will be registered in
our shortcuts preferences page
"""
+16 -16
Ver Arquivo
@@ -75,7 +75,7 @@ class DefaultsConfig(cp.ConfigParser):
key = " = ".join((key, value.replace('\n', '\n\t')))
fp.write("%s\n" % (key))
fp.write("\n")
def _set(self, section, option, value, verbose):
"""
Private set method
@@ -154,13 +154,13 @@ class DefaultsConfig(cp.ConfigParser):
os.mkdir(folder)
config_file = osp.join(folder, '%s.ini' % self.name)
return config_file
def set_defaults(self, defaults):
for section, options in defaults:
for option in options:
new_value = options[ option ]
self._set(section, option, new_value, False)
#==============================================================================
# User config class
@@ -173,7 +173,7 @@ class UserConfig(DefaultsConfig):
*or* list of tuples (section_name, options)
version: version of the configuration file (X.Y.Z format)
subfolder: configuration file will be saved in %home%/subfolder/%name%.ini
Note that 'get' and 'set' arguments number and type
differ from the overriden methods
"""
@@ -231,11 +231,11 @@ class UserConfig(DefaultsConfig):
if defaults is None:
# If no defaults are defined, set .ini file settings as default
self.set_as_defaults()
def get_version(self, version='0.0.0'):
"""Return configuration (not application!) version"""
return self.get(self.DEFAULT_SECTION_NAME, 'version', version)
def set_version(self, version='0.0.0', save=True):
"""Set configuration (not application!) version"""
self.set(self.DEFAULT_SECTION_NAME, 'version', version, save=save)
@@ -259,7 +259,7 @@ class UserConfig(DefaultsConfig):
self.read(self.filename(), encoding='utf-8')
except cp.MissingSectionHeaderError:
print("Warning: File contains no section headers.") # spyder: test-skip
def _load_old_defaults(self, old_version):
"""Read old defaults"""
old_defaults = cp.ConfigParser()
@@ -270,7 +270,7 @@ class UserConfig(DefaultsConfig):
path = osp.join(path, 'defaults')
old_defaults.read(osp.join(path, 'defaults-'+old_version+'.ini'))
return old_defaults
def _save_new_defaults(self, defaults, new_version, subfolder):
"""Save new defaults"""
new_defaults = DefaultsConfig(name='defaults-'+new_version,
@@ -278,7 +278,7 @@ class UserConfig(DefaultsConfig):
if not osp.isfile(new_defaults.filename()):
new_defaults.set_defaults(defaults)
new_defaults._save()
def _update_defaults(self, defaults, old_version, verbose=False):
"""Update defaults after a change in version"""
old_defaults = self._load_old_defaults(old_version)
@@ -292,7 +292,7 @@ class UserConfig(DefaultsConfig):
if old_value is None or \
to_text_string(new_value) != old_value:
self._set(section, option, new_value, verbose)
def _remove_deprecated_options(self, old_version):
"""
Remove options which are present in the .ini file but not in defaults
@@ -336,7 +336,7 @@ class UserConfig(DefaultsConfig):
self._set(sec, option, value, verbose)
if save:
self._save()
def _check_section_option(self, section, option):
"""
Private method to check section and option types
@@ -361,7 +361,7 @@ class UserConfig(DefaultsConfig):
return options[ option ]
else:
return NoDefault
def get(self, section, option, default=NoDefault):
"""
Get an option
@@ -376,14 +376,14 @@ class UserConfig(DefaultsConfig):
raise cp.NoSectionError(section)
else:
self.add_section(section)
if not self.has_option(section, option):
if default is NoDefault:
raise cp.NoOptionError(option, section)
else:
self.set(section, option, default)
return default
value = cp.ConfigParser.get(self, section, option, raw=self.raw)
# Use type of default_value to parse value correctly
default_value = self.get_default(section, option)
@@ -450,11 +450,11 @@ class UserConfig(DefaultsConfig):
self._set(section, option, value, verbose)
if save:
self._save()
def remove_section(self, section):
cp.ConfigParser.remove_section(self, section)
self._save()
def remove_option(self, section, option):
cp.ConfigParser.remove_option(self, section, option)
self._save()
+1 -1
Ver Arquivo
@@ -51,7 +51,7 @@ class Dependency(object):
return '%s (%s)' % (self.installed_version, self.OK)
else:
return '%s (%s)' % (self.installed_version, self.NOK)
def get_status(self):
"""Return dependency status (string)"""
if self.check():
@@ -44,7 +44,7 @@ locale_codec = QTextCodec.codecForLocale()
class BreakpointTableModel(QAbstractTableModel):
"""
Table model for breakpoints dictionary
"""
def __init__(self, parent, data):
QAbstractTableModel.__init__(self, parent)
@@ -53,7 +53,7 @@ class BreakpointTableModel(QAbstractTableModel):
self._data = None
self.breakpoints = None
self.set_data(data)
def set_data(self, data):
"""Set model data"""
self._data = data
@@ -65,11 +65,11 @@ class BreakpointTableModel(QAbstractTableModel):
for item in data[key]:
self.breakpoints.append((key, item[0], item[1], ""))
self.reset()
def rowCount(self, qindex=QModelIndex()):
"""Array row number"""
return len(self.breakpoints)
def columnCount(self, qindex=QModelIndex()):
"""Array column count"""
return 4
@@ -99,11 +99,11 @@ class BreakpointTableModel(QAbstractTableModel):
return to_qvariant( headers[i_column] )
else:
return to_qvariant()
def get_value(self, index):
"""Return current value"""
return self.breakpoints[index.row()][index.column()]
def data(self, index, role=Qt.DisplayRole):
"""Return data at table index"""
if not index.isValid():
@@ -128,7 +128,7 @@ class BreakpointTableModel(QAbstractTableModel):
self.beginResetModel()
self.endResetModel()
class BreakpointDelegate(QItemDelegate):
def __init__(self, parent=None):
QItemDelegate.__init__(self, parent)
@@ -139,7 +139,7 @@ class BreakpointTableView(QTableView):
clear_breakpoint = Signal(str, int)
clear_all_breakpoints = Signal()
set_or_edit_conditional_breakpoint = Signal()
def __init__(self, parent, data):
QTableView.__init__(self, parent)
self.model = BreakpointTableModel(self, data)
@@ -148,7 +148,7 @@ class BreakpointTableView(QTableView):
self.setItemDelegate(self.delegate)
self.setup_table()
def setup_table(self):
"""Setup table"""
self.horizontalHeader().setStretchLastSection(True)
@@ -157,12 +157,12 @@ class BreakpointTableView(QTableView):
# Sorting columns
self.setSortingEnabled(False)
self.sortByColumn(0, Qt.DescendingOrder)
def adjust_columns(self):
"""Resize three first columns to contents"""
for col in range(3):
self.resizeColumnToContents(col)
def mouseDoubleClickEvent(self, event):
"""Reimplement Qt method"""
index_clicked = self.indexAt(event.pos())
@@ -172,7 +172,7 @@ class BreakpointTableView(QTableView):
self.edit_goto.emit(filename, int(line_number_str), '')
if index_clicked.column()==2:
self.set_or_edit_conditional_breakpoint.emit()
def contextMenuEvent(self, event):
index_clicked = self.indexAt(event.pos())
actions = []
@@ -221,10 +221,10 @@ class BreakpointWidget(QWidget):
set_or_edit_conditional_breakpoint = Signal()
clear_breakpoint = Signal(str, int)
edit_goto = Signal(str, int, str)
def __init__(self, parent, options_button=None):
QWidget.__init__(self, parent)
self.setWindowTitle("Breakpoints")
self.dictwidget = BreakpointTableView(self,
self._load_all_breakpoints())
@@ -246,17 +246,17 @@ class BreakpointWidget(QWidget):
lambda s1, lino, s2: self.edit_goto.emit(s1, lino, s2))
self.dictwidget.set_or_edit_conditional_breakpoint.connect(
lambda: self.set_or_edit_conditional_breakpoint.emit())
def _load_all_breakpoints(self):
bp_dict = CONF.get('run', 'breakpoints', {})
for filename in list(bp_dict.keys()):
if not osp.isfile(filename):
bp_dict.pop(filename)
return bp_dict
def get_data(self):
pass
def set_data(self):
bp_dict = self._load_all_breakpoints()
self.dictwidget.model.set_data(bp_dict)
+3 -3
Ver Arquivo
@@ -55,7 +55,7 @@ class ANSIEscapeCodeHandler(object):
self.background_color = None
self.default_foreground_color = 30
self.default_background_color = 47
def set_code(self, code):
assert isinstance(code, int)
if code == 0:
@@ -96,7 +96,7 @@ class ANSIEscapeCodeHandler(object):
# Default background color
self.background_color = self.default_background_color
self.set_style()
def set_style(self):
"""
Set font style with the following attributes:
@@ -104,7 +104,7 @@ class ANSIEscapeCodeHandler(object):
'bold' and 'underline'
"""
raise NotImplementedError
def reset(self):
self.current_format = None
self.intensity = 0
+27 -27
Ver Arquivo
@@ -57,42 +57,42 @@ class Interpreter(InteractiveConsole, threading.Thread):
"""
InteractiveConsole.__init__(self, namespace)
threading.Thread.__init__(self)
self._id = None
self.exit_flag = False
self.debug = debug
# Execution Status
self.more = False
if exitfunc is not None:
atexit.register(exitfunc)
self.namespace = self.locals
self.namespace['__name__'] = '__main__'
self.namespace['execfile'] = self.execfile
self.namespace['runfile'] = self.runfile
self.namespace['raw_input'] = self.raw_input_replacement
self.namespace['help'] = self.help_replacement
# Capture all interactive input/output
self.initial_stdout = sys.stdout
self.initial_stderr = sys.stderr
self.initial_stdin = sys.stdin
# Create communication pipes
pr, pw = os.pipe()
self.stdin_read = os.fdopen(pr, "r")
self.stdin_write = os.fdopen(pw, "wb", 0)
self.stdout_write = Output()
self.stderr_write = Output()
self.input_condition = threading.Condition()
self.widget_proxy = WidgetProxy(self.input_condition)
self.redirect_stds()
#------ Standard input/output
def redirect_stds(self):
@@ -101,7 +101,7 @@ class Interpreter(InteractiveConsole, threading.Thread):
sys.stdout = self.stdout_write
sys.stderr = self.stderr_write
sys.stdin = self.stdin_read
def restore_stds(self):
"""Restore stds"""
if not self.debug:
@@ -118,7 +118,7 @@ class Interpreter(InteractiveConsole, threading.Thread):
inp = self.widget_proxy.input_data
self.input_condition.release()
return inp
def help_replacement(self, text=None, interactive=False):
"""For help builtin function emulation"""
if text is not None and not interactive:
@@ -182,7 +182,7 @@ has the same effect as typing a particular string at the help> prompt.
elif cd_match:
cmd = 'import os; os.chdir(r"%s")' % cd_match.groups()[0].strip()
# -- End of Special commands type I
# -- Special commands type II
# (don't need code execution in interpreter)
xedit_match = re.match(special_pattern % 'xedit', cmd)
@@ -226,24 +226,24 @@ has the same effect as typing a particular string at the help> prompt.
# self.widget_proxy.set_readonly(True)
self.more = self.push(cmd)
# self.widget_proxy.set_readonly(False)
if new_prompt:
self.widget_proxy.new_prompt(self.p2 if self.more else self.p1)
if not self.more:
self.resetbuffer()
def run(self):
"""Wait for input and run it"""
while not self.exit_flag:
self.run_line()
def run_line(self):
line = self.stdin_read.readline()
if self.exit_flag:
return
# Remove last character which is always '\n':
self.run_command(line[:-1])
def get_thread_id(self):
"""Return thread id"""
if self._id is None:
@@ -251,7 +251,7 @@ has the same effect as typing a particular string at the help> prompt.
if obj is self:
self._id = thread_id
return self._id
def raise_keyboard_interrupt(self):
if self.isAlive():
ctypes.pythonapi.PyThreadState_SetAsyncExc(self.get_thread_id(),
@@ -259,12 +259,12 @@ has the same effect as typing a particular string at the help> prompt.
return True
else:
return False
def closing(self):
"""Actions to be done before restarting this interpreter"""
pass
def execfile(self, filename):
"""Exec filename"""
source = open(filename, 'r').read()
@@ -278,7 +278,7 @@ has the same effect as typing a particular string at the help> prompt.
InteractiveConsole.showsyntaxerror(self, filename)
else:
self.runcode(code)
def runfile(self, filename, args=None):
"""
Run filename
@@ -294,7 +294,7 @@ has the same effect as typing a particular string at the help> prompt.
self.execfile(filename)
sys.argv = ['']
self.namespace.pop('__file__')
def eval(self, text):
"""
Evaluate text and return (obj, valid)
@@ -306,19 +306,19 @@ has the same effect as typing a particular string at the help> prompt.
return eval(text, self.locals), True
except:
return None, False
def is_defined(self, objtxt, force_import=False):
"""Return True if object is defined"""
return isdefined(objtxt, force_import=force_import,
namespace=self.locals)
#===========================================================================
# InteractiveConsole API
#===========================================================================
def push(self, line):
"""
Push a line of source text to the interpreter
The line should not have a trailing newline; it may have internal
newlines. The line is appended to a buffer and the interpreters
runsource() method is called with the concatenated contents of the
@@ -329,8 +329,8 @@ has the same effect as typing a particular string at the help> prompt.
was dealt with in some way (this is the same as runsource()).
"""
return InteractiveConsole.push(self, "#coding=utf-8\n" + line)
def resetbuffer(self):
"""Remove any unhandled source text from the input buffer"""
InteractiveConsole.resetbuffer(self)
+38 -38
Ver Arquivo
@@ -58,12 +58,12 @@ def create_banner(message):
class SysOutput(QObject):
"""Handle standard I/O queue"""
data_avail = Signal()
def __init__(self):
QObject.__init__(self)
self.queue = []
self.lock = threading.Lock()
def write(self, val):
self.lock.acquire()
self.queue.append(val)
@@ -76,7 +76,7 @@ class SysOutput(QObject):
self.queue = []
self.lock.release()
return s
# We need to add this method to fix Issue 1789
def flush(self):
pass
@@ -91,34 +91,34 @@ class WidgetProxyData(object):
class WidgetProxy(QObject):
"""Handle Shell widget refresh signal"""
sig_new_prompt = Signal(str)
sig_set_readonly = Signal(bool)
sig_edit = Signal(str, bool)
sig_wait_input = Signal(str)
def __init__(self, input_condition):
QObject.__init__(self)
self.input_data = None
self.input_condition = input_condition
def new_prompt(self, prompt):
self.sig_new_prompt.emit(prompt)
def set_readonly(self, state):
self.sig_set_readonly.emit(state)
def edit(self, filename, external_editor=False):
self.sig_edit.emit(filename, external_editor)
def data_available(self):
"""Return True if input data is available"""
return self.input_data is not WidgetProxyData
def wait_input(self, prompt=''):
self.input_data = WidgetProxyData
self.sig_wait_input.emit(prompt)
def end_input(self, cmd):
self.input_condition.acquire()
self.input_data = cmd
@@ -128,12 +128,12 @@ class WidgetProxy(QObject):
class InternalShell(PythonShellWidget):
"""Shell base widget: link between PythonShellWidget and Interpreter"""
status = Signal(str)
refresh = Signal()
go_to_error = Signal(str)
focus_changed = Signal()
def __init__(self, parent=None, namespace=None, commands=[], message=None,
max_line_count=300, font=None, exitfunc=None, profile=False,
multithreaded=True):
@@ -150,11 +150,11 @@ class InternalShell(PythonShellWidget):
# Allow raw_input support:
self.input_loop = None
self.input_mode = False
# KeyboardInterrupt support
self.interrupted = False # used only for not-multithreaded mode
self.sig_keyboard_interrupt.connect(self.keyboard_interrupt)
# Code completion / calltips
getcfg = lambda option: CONF.get('internal_console', option)
@@ -167,10 +167,10 @@ class InternalShell(PythonShellWidget):
self.message = message
self.interpreter = None
self.start_interpreter(namespace)
# Clear status bar
self.status.emit('')
# Embedded shell -- requires the monitor (which installs the
# 'open_in_spyder' function in builtins)
if hasattr(builtins, 'open_in_spyder'):
@@ -180,7 +180,7 @@ class InternalShell(PythonShellWidget):
def start_interpreter(self, namespace):
"""Start Python interpreter"""
self.clear()
if self.interpreter is not None:
self.interpreter.closing()
self.interpreter = Interpreter(namespace, self.exitfunc,
@@ -194,7 +194,7 @@ class InternalShell(PythonShellWidget):
self.interpreter.widget_proxy.sig_wait_input.connect(self.wait_input)
if self.multithreaded:
self.interpreter.start()
# Interpreter banner
banner = create_banner(self.message)
self.write(banner, prompt=True)
@@ -202,7 +202,7 @@ class InternalShell(PythonShellWidget):
# Initial commands
for cmd in self.commands:
self.run_command(cmd, history=False, new_prompt=False)
# First prompt
self.new_prompt(self.interpreter.p1)
self.refresh.emit()
@@ -215,27 +215,27 @@ class InternalShell(PythonShellWidget):
if self.multithreaded:
self.interpreter.stdin_write.write(to_binary_string('\n'))
self.interpreter.restore_stds()
def edit_script(self, filename, external_editor):
filename = to_text_string(filename)
if external_editor:
self.external_editor(filename)
else:
self.parent().edit_script(filename)
def stdout_avail(self):
"""Data is available in stdout, let's empty the queue and write it!"""
data = self.interpreter.stdout_write.empty_queue()
if data:
self.write(data)
def stderr_avail(self):
"""Data is available in stderr, let's empty the queue and write it!"""
data = self.interpreter.stderr_write.empty_queue()
if data:
self.write(data, error=True)
self.flush(error=True)
#------Raw input support
def wait_input(self, prompt=''):
@@ -246,7 +246,7 @@ class InternalShell(PythonShellWidget):
self.input_loop = QEventLoop()
self.input_loop.exec_()
self.input_loop = None
def end_input(self, cmd):
"""End of wait_input mode"""
self.input_mode = False
@@ -349,13 +349,13 @@ class InternalShell(PythonShellWidget):
# Event was accepted in self.preprocess_keyevent
return
self.postprocess_keyevent(event)
def __flush_eventqueue(self):
"""Flush keyboard event queue"""
while self.eventqueue:
past_event = self.eventqueue.pop(0)
self.postprocess_keyevent(past_event)
#------ Command execution
def keyboard_interrupt(self):
"""Simulate keyboard interrupt"""
@@ -382,7 +382,7 @@ class InternalShell(PythonShellWidget):
self.write(line+os.linesep, flush=True)
self.execute_command(line+"\n")
self.flush()
def execute_command(self, cmd):
"""
Execute a command
@@ -398,7 +398,7 @@ class InternalShell(PythonShellWidget):
self.clear_terminal()
return
self.run_command(cmd)
def run_command(self, cmd, history=True, new_prompt=True):
"""Run command in interpreter"""
if not cmd:
@@ -419,51 +419,51 @@ class InternalShell(PythonShellWidget):
error=True)
else:
self.interpreter.stdin_write.write(to_binary_string(cmd + '\n'))
#------ Code completion / Calltips
def _eval(self, text):
"""Is text a valid object?"""
return self.interpreter.eval(text)
def get_dir(self, objtxt):
"""Return dir(object)"""
obj, valid = self._eval(objtxt)
if valid:
return getobjdir(obj)
def get_globals_keys(self):
"""Return shell globals() keys"""
return list(self.interpreter.namespace.keys())
def get_cdlistdir(self):
"""Return shell current directory list dir"""
return os.listdir(getcwd_or_home())
def iscallable(self, objtxt):
"""Is object callable?"""
obj, valid = self._eval(objtxt)
if valid:
return callable(obj)
def get_arglist(self, objtxt):
"""Get func/method argument list"""
obj, valid = self._eval(objtxt)
if valid:
return getargtxt(obj)
def get__doc__(self, objtxt):
"""Get object __doc__"""
obj, valid = self._eval(objtxt)
if valid:
return obj.__doc__
def get_doc(self, objtxt):
"""Get object documentation dictionary"""
obj, valid = self._eval(objtxt)
if valid:
return getdoc(obj)
def get_source(self, objtxt):
"""Get object source"""
obj, valid = self._eval(objtxt)
+73 -73
Ver Arquivo
@@ -46,12 +46,12 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
"""
Shell base widget
"""
redirect_stdio = Signal(bool)
sig_keyboard_interrupt = Signal()
execute = Signal(str)
append_to_history = Signal(str, str)
def __init__(self, parent, history_filename, profile=False,
initial_message=None, default_foreground_color=None,
error_foreground_color=None, traceback_foreground_color=None,
@@ -62,26 +62,26 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
ConsoleBaseWidget.__init__(self, parent)
SaveHistoryMixin.__init__(self, history_filename)
BrowseHistoryMixin.__init__(self)
# Prompt position: tuple (line, index)
self.current_prompt_pos = None
self.new_input_line = True
# History
assert is_text_string(history_filename)
self.history = self.load_history()
# Session
self.historylog_filename = CONF.get('main', 'historylog_filename',
get_conf_path('history.log'))
# Context menu
self.menu = None
self.setup_context_menu()
# Simple profiling test
self.profile = profile
# Buffer to increase performance of write/flush operations
self.__buffer = []
if initial_message:
@@ -149,7 +149,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
add_actions(self.menu, (self.cut_action, self.copy_action,
paste_action, self.delete_action, None,
selectall_action, None, save_action) )
def contextMenuEvent(self, event):
"""Reimplement Qt method"""
state = self.has_selected_text()
@@ -158,12 +158,12 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.delete_action.setEnabled(state)
self.menu.popup(event.globalPos())
event.accept()
#------ Input buffer
def get_current_line_from_cursor(self):
return self.get_text('cursor', 'eof')
def _select_input(self):
"""Select current line (without selecting console prompt)"""
line, index = self.get_position('eof')
@@ -199,7 +199,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
return input_buffer
input_buffer = Property("QString", _get_input_buffer, _set_input_buffer)
#------ Prompt
def new_prompt(self, prompt):
@@ -213,7 +213,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.current_prompt_pos = self.get_position('cursor')
self.ensureCursorVisible()
self.new_input_line = False
def check_selection(self):
"""
Check if selected text is r/w,
@@ -223,7 +223,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.set_cursor_position('eof')
else:
self.truncate_selection(self.current_prompt_pos)
#------ Copy / Keyboard interrupt
@Slot()
@@ -274,12 +274,12 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
def on_enter(self, command):
"""on_enter"""
self.execute_command(command)
def execute_command(self, command):
self.execute.emit(command)
self.add_to_history(command)
self.new_input_line = True
def on_new_line(self):
"""On new input line"""
self.set_cursor_position('eof')
@@ -292,7 +292,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
if self.new_input_line:
self.on_new_line()
ConsoleBaseWidget.paste(self)
def keyPressEvent(self, event):
"""
Reimplement Qt Method
@@ -303,7 +303,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
# Event was accepted in self.preprocess_keyevent
return
self.postprocess_keyevent(event)
def preprocess_keyevent(self, event):
"""Pre-process keypress event:
return True if event is accepted, false otherwise"""
@@ -320,25 +320,25 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.copy()
event.accept()
return True
if self.new_input_line and ( len(event.text()) or event.key() in \
(Qt.Key_Up, Qt.Key_Down, Qt.Key_Left, Qt.Key_Right) ):
self.on_new_line()
return False
def postprocess_keyevent(self, event):
"""Post-process keypress event:
in InternalShell, this is method is called when shell is ready"""
event, text, key, ctrl, shift = restore_keyevent(event)
# Is cursor on the last line? and after prompt?
if len(text):
#XXX: Shouldn't it be: `if len(unicode(text).strip(os.linesep))` ?
if self.has_selected_text():
self.check_selection()
self.restrict_cursor_position(self.current_prompt_pos, 'eof')
cursor_position = self.get_position('cursor')
if key in (Qt.Key_Return, Qt.Key_Enter):
@@ -347,23 +347,23 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
# add and run selection
else:
self.insert_text(self.get_selected_text(), at_end=True)
elif key == Qt.Key_Insert and not shift and not ctrl:
self.setOverwriteMode(not self.overwriteMode())
elif key == Qt.Key_Delete:
if self.has_selected_text():
self.check_selection()
self.remove_selected_text()
elif self.is_cursor_on_last_line():
self.stdkey_clear()
elif key == Qt.Key_Backspace:
self._key_backspace(cursor_position)
elif key == Qt.Key_Tab:
self._key_tab()
elif key == Qt.Key_Space and ctrl:
self._key_ctrl_space()
@@ -374,7 +374,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
method = self.extend_selection_to_next if shift \
else self.move_cursor_to_next
method('word' if ctrl else 'character', direction='left')
elif key == Qt.Key_Right:
if self.is_cursor_at_end():
return
@@ -397,7 +397,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.stdkey_up(shift)
else:
self.browse_history(backward=True)
elif key == Qt.Key_Down:
if not self.is_cursor_on_last_line():
self.set_cursor_position('eof')
@@ -407,7 +407,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.stdkey_down(shift)
else:
self.browse_history(backward=False)
elif key in (Qt.Key_PageUp, Qt.Key_PageDown):
#XXX: Find a way to do this programmatically instead of calling
# widget keyhandler (this won't work if the *event* is coming from
@@ -419,31 +419,31 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
elif key == Qt.Key_Escape:
self._key_escape()
elif key == Qt.Key_L and ctrl:
self.clear_terminal()
elif key == Qt.Key_V and ctrl:
self.paste()
elif key == Qt.Key_X and ctrl:
self.cut()
elif key == Qt.Key_Z and ctrl:
self.undo()
elif key == Qt.Key_Y and ctrl:
self.redo()
elif key == Qt.Key_A and ctrl:
self.selectAll()
elif key == Qt.Key_Question and not self.has_selected_text():
self._key_question(text)
elif key == Qt.Key_ParenLeft and not self.has_selected_text():
self._key_parenleft(text)
elif key == Qt.Key_Period and not self.has_selected_text():
self._key_period(text)
@@ -451,11 +451,11 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
self.hist_wholeline = False
self.insert_text(text)
self._key_other(text)
else:
# Let the parent widget handle the key press event
ConsoleBaseWidget.keyPressEvent(self, event)
#------ Key handlers
def _key_enter(self):
@@ -490,7 +490,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
def _key_period(self, text):
raise NotImplementedError
#------ History Management
def load_history(self):
"""Load history from a .py file in user home directory"""
@@ -580,7 +580,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
# Insert text at current cursor position
ConsoleBaseWidget.insert_text(self, text)
#------ Re-implemented Qt Methods
def focusNextPrevChild(self, next):
"""
@@ -590,7 +590,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
return False
return ConsoleBaseWidget.focusNextPrevChild(self, next)
#------ Drag and drop
def dragEnterEvent(self, event):
"""Drag and Drop - Enter event"""
@@ -616,7 +616,7 @@ class ShellBaseWidget(ConsoleBaseWidget, SaveHistoryMixin,
event.accept()
else:
event.ignore()
def drop_pathlist(self, pathlist):
"""Drop path list"""
raise NotImplementedError
@@ -635,7 +635,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
'# *** Spyder Python Console History Log ***',]
SEPARATOR = '%s##---(%s)---' % (os.linesep*2, time.ctime())
go_to_error = Signal(str)
def __init__(self, parent, history_filename, profile=False, initial_message=None):
ShellBaseWidget.__init__(self, parent, history_filename,
profile=profile,
@@ -658,7 +658,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
name='Inspect current object',
parent=self)
return [inspectsc, array_inline, array_table]
def get_shortcut_data(self):
"""
Returns shortcut data, a list of tuples (shortcut, text, default)
@@ -691,7 +691,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
triggered=self.clear_terminal)
add_actions(self.menu, (self.copy_without_prompts_action,
clear_line_action, clear_action))
def contextMenuEvent(self, event):
"""Reimplements ShellBaseWidget method"""
state = self.has_selected_text()
@@ -708,7 +708,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
lines[index] = line[4:]
text = os.linesep.join(lines)
QApplication.clipboard().setText(text)
#------ Key handlers
def postprocess_keyevent(self, event):
@@ -717,12 +717,12 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
if QToolTip.isVisible():
_event, _text, key, _ctrl, _shift = restore_keyevent(event)
self.hide_tooltip_if_necessary(key)
def _key_other(self, text):
"""1 character key"""
if self.is_completion_widget_visible():
self.completion_text += text
def _key_backspace(self, cursor_position):
"""Action for Backspace key"""
if self.has_selected_text():
@@ -737,7 +737,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
# Removing only last character because if there was a selection
# the completion widget would have been canceled
self.completion_text = self.completion_text[:-1]
def _key_tab(self):
"""Action for TAB key"""
if self.is_cursor_on_last_line():
@@ -746,20 +746,20 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
self.stdkey_tab()
else:
self.show_code_completion()
def _key_ctrl_space(self):
"""Action for Ctrl+Space"""
if not self.is_completion_widget_visible():
self.show_code_completion()
def _key_pageup(self):
"""Action for PageUp key"""
pass
def _key_pagedown(self):
"""Action for PageDown key"""
pass
def _key_escape(self):
"""Action for ESCAPE key"""
if self.is_completion_widget_visible():
@@ -775,7 +775,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
# In case calltip and completion are shown at the same time:
if self.is_completion_widget_visible():
self.completion_text += '?'
def _key_parenleft(self, text):
"""Action for '('"""
self.hide_completion_widget()
@@ -786,7 +786,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
self.show_object_info(last_obj, call=True)
return
self.insert_text(text)
def _key_period(self, text):
"""Action for '.'"""
self.insert_text(text)
@@ -814,7 +814,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
else:
# Standard paste
ShellBaseWidget.paste(self)
#------ Code Completion / Calltips
# Methods implemented in child class:
@@ -886,7 +886,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
if last_obj and obj_dir and text.endswith('.'):
self.show_completion_list(obj_dir)
return
# Builtins and globals
if not text.endswith('.') and last_obj \
and re.match(r'[a-zA-Z_0-9]*$', last_obj):
@@ -897,7 +897,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
return
else:
return
# Looking for an incomplete completion
if last_obj is None:
last_obj = text
@@ -913,7 +913,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
self.show_completion_list(completions,
completion_text=completion_text)
return
# Looking for ' or ": filename completion
q_pos = max([text.rfind("'"), text.rfind('"')])
if q_pos != -1:
@@ -929,7 +929,7 @@ class PythonShellWidget(TracebackLinksMixin, ShellBaseWidget,
code completion.
"""
pass
#------ Drag'n Drop
def drop_pathlist(self, pathlist):
"""Drop path list"""
@@ -953,15 +953,15 @@ class TerminalWidget(ShellBaseWidget):
INITHISTORY = ['%s *** Spyder Terminal History Log ***' % COM, COM,]
SEPARATOR = '%s%s ---(%s)---' % (os.linesep*2, COM, time.ctime())
go_to_error = Signal(str)
def __init__(self, parent, history_filename, profile=False):
ShellBaseWidget.__init__(self, parent, history_filename, profile)
#------ Key handlers
def _key_other(self, text):
"""1 character key"""
pass
def _key_backspace(self, cursor_position):
"""Action for Backspace key"""
if self.has_selected_text():
@@ -972,32 +972,32 @@ class TerminalWidget(ShellBaseWidget):
return
elif self.is_cursor_on_last_line():
self.stdkey_backspace()
def _key_tab(self):
"""Action for TAB key"""
if self.is_cursor_on_last_line():
self.stdkey_tab()
def _key_ctrl_space(self):
"""Action for Ctrl+Space"""
pass
def _key_escape(self):
"""Action for ESCAPE key"""
self.clear_line()
def _key_question(self, text):
"""Action for '?'"""
self.insert_text(text)
def _key_parenleft(self, text):
"""Action for '('"""
self.insert_text(text)
def _key_period(self, text):
"""Action for '.'"""
self.insert_text(text)
#------ Drag'n Drop
def drop_pathlist(self, pathlist):
+1 -1
Ver Arquivo
@@ -136,7 +136,7 @@ class Editor(SpyderPluginWidget):
self.editorwindows_to_be_created = []
self.toolbar_list = None
self.menu_list = None
# Initialize plugin
self.initialize_plugin()
self.options_button.hide()
@@ -39,7 +39,7 @@ def test_no_auto_colon_after_simple_statement():
def test_auto_colon_after_if_statement():
editor = construct_editor("if x == 1")
assert editor.autoinsert_colons() == True
def test_no_auto_colon_if_not_at_end_of_line():
editor = construct_editor("if x == 1")
cursor = editor.textCursor()
@@ -75,7 +75,7 @@ def test_no_auto_colon_in_listcomp_over_two_lines():
editor = construct_editor("ns = [ n for ns in range(10) \n if n < 5 ]")
assert editor.autoinsert_colons() == False
# --- Failing tests
# -----------------------------------------------------------------------------
@pytest.mark.xfail
@@ -96,7 +96,7 @@ def test_no_auto_colon_in_listcomp_over_three_lines():
def test_auto_colon_in_two_if_statements_on_one_line():
editor = construct_editor("if x < 0: x = 0; if x == 0")
assert editor.autoinsert_colons() == True
if __name__ == "__main__":
pytest.main()
+14 -14
Ver Arquivo
@@ -157,7 +157,7 @@ def test_find_number_matches(setup_editor):
def test_move_current_line_up(editor_bot):
editor_stack, editor = editor_bot
# Move second line up when nothing is selected.
editor.go_to_line(2)
editor.move_line_up()
@@ -166,11 +166,11 @@ def test_move_current_line_up(editor_bot):
'\n'
'x = 2\n')
assert editor.toPlainText() == expected_new_text
# Move line up when already at the top.
editor.move_line_up()
assert editor.toPlainText() == expected_new_text
# Move fourth line up when part of the line is selected.
editor.go_to_line(4)
editor.moveCursor(QTextCursor.Right, QTextCursor.MoveAnchor)
@@ -186,7 +186,7 @@ def test_move_current_line_up(editor_bot):
def test_move_current_line_down(editor_bot):
editor_stack, editor = editor_bot
# Move fourth line down when nothing is selected.
editor.go_to_line(4)
editor.move_line_down()
@@ -196,11 +196,11 @@ def test_move_current_line_down(editor_bot):
'\n'
'x = 2')
assert editor.toPlainText() == expected_new_text
# Move line down when already at the bottom.
editor.move_line_down()
assert editor.toPlainText() == expected_new_text
# Move first line down when part of the line is selected.
editor.go_to_line(1)
editor.moveCursor(QTextCursor.Right, QTextCursor.MoveAnchor)
@@ -213,11 +213,11 @@ def test_move_current_line_down(editor_bot):
'\n'
'x = 2')
assert editor.toPlainText() == expected_new_text
def test_move_multiple_lines_up(editor_bot):
editor_stack, editor = editor_bot
# Move second and third lines up.
editor.go_to_line(2)
cursor = editor.textCursor()
@@ -225,13 +225,13 @@ def test_move_multiple_lines_up(editor_bot):
cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
editor.setTextCursor(cursor)
editor.move_line_up()
expected_new_text = ('print(a)\n'
'\n'
'a = 1\n'
'x = 2\n')
assert editor.toPlainText() == expected_new_text
# Move first and second lines up (to test already at top condition).
editor.move_line_up()
assert editor.toPlainText() == expected_new_text
@@ -239,7 +239,7 @@ def test_move_multiple_lines_up(editor_bot):
def test_move_multiple_lines_down(editor_bot):
editor_stack, editor = editor_bot
# Move third and fourth lines down.
editor.go_to_line(3)
cursor = editor.textCursor()
@@ -247,19 +247,19 @@ def test_move_multiple_lines_down(editor_bot):
cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
editor.setTextCursor(cursor)
editor.move_line_down()
expected_new_text = ('a = 1\n'
'print(a)\n'
'\n'
'\n'
'x = 2')
assert editor.toPlainText() == expected_new_text
# Move fourht and fifth lines down (to test already at bottom condition).
editor.move_line_down()
assert editor.toPlainText() == expected_new_text
def test_run_top_line(editor_bot, qtbot):
editor_stack, editor = editor_bot
editor.go_to_line(1) # line number is one based
+58 -58
Ver Arquivo
@@ -162,7 +162,7 @@ class DirView(QTreeView):
self._scrollbar_positions = None
self.setSelectionMode(self.ExtendedSelection)
self.shortcuts = self.create_shortcuts()
#---- Model
def setup_fs_model(self):
"""Setup filesystem model"""
@@ -170,11 +170,11 @@ class DirView(QTreeView):
self.fsmodel = QFileSystemModel(self)
self.fsmodel.setFilter(filters)
self.fsmodel.setNameFilterDisables(False)
def install_model(self):
"""Install filesystem model"""
self.setModel(self.fsmodel)
def setup_view(self):
"""Setup view"""
self.install_model()
@@ -198,23 +198,23 @@ class DirView(QTreeView):
"""Set name filters"""
self.name_filters = name_filters
self.fsmodel.setNameFilters(name_filters)
def set_show_all(self, state):
"""Toggle 'show all files' state"""
if state:
self.fsmodel.setNameFilters([])
else:
self.fsmodel.setNameFilters(self.name_filters)
def get_filename(self, index):
"""Return filename associated with *index*"""
if index:
return osp.normpath(to_text_string(self.fsmodel.filePath(index)))
def get_index(self, filename):
"""Return index associated with filename"""
return self.fsmodel.index(filename)
def get_selected_filenames(self):
"""Return selected filenames"""
if self.selectionMode() == self.ExtendedSelection:
@@ -224,7 +224,7 @@ class DirView(QTreeView):
self.selectionModel().selectedRows()]
else:
return [self.get_filename(self.currentIndex())]
def get_dirname(self, index):
"""Return dirname associated with *index*"""
fname = self.get_filename(index)
@@ -233,7 +233,7 @@ class DirView(QTreeView):
return fname
else:
return osp.dirname(fname)
#---- Tree view widget
def setup(self, name_filters=['*.py', '*.pyw'], show_all=False,
single_click_to_open=False):
@@ -243,7 +243,7 @@ class DirView(QTreeView):
self.set_name_filters(name_filters)
self.show_all = show_all
self.single_click_to_open = single_click_to_open
# Setup context menu
self.menu = QMenu(self)
self.common_actions = self.setup_common_actions()
@@ -252,7 +252,7 @@ class DirView(QTreeView):
"""Reset file system model icon provider
The purpose of this is to refresh files/directories icons"""
self.fsmodel.setIconProvider(IconProvider(self))
#---- Context menu
def setup_common_actions(self):
"""Setup context menu common actions"""
@@ -293,7 +293,7 @@ class DirView(QTreeView):
self.parent_widget.sig_option_changed.emit('show_all', checked)
self.show_all = checked
self.set_show_all(checked)
def create_file_new_actions(self, fnames):
"""Return actions for submenu 'New...'"""
if not fnames:
@@ -316,7 +316,7 @@ class DirView(QTreeView):
self.new_package(fnames[-1]))
return [new_file_act, new_folder_act, None,
new_module_act, new_package_act]
def create_file_import_actions(self, fnames):
"""Return actions for submenu 'Import...'"""
return []
@@ -365,13 +365,13 @@ class DirView(QTreeView):
create_action(self, _("Copy Relative Path"), QKeySequence(
get_shortcut('explorer', 'copy relative path')),
triggered=self.copy_relative_path))
actions = []
if only_modules:
actions.append(run_action)
if only_valid and only_files:
actions.append(edit_action)
if sys.platform == 'darwin':
text=_("Show in Finder")
else:
@@ -424,7 +424,7 @@ class DirView(QTreeView):
self.open_interpreter(fnames))
actions.append(action)
return actions
def create_context_menu_actions(self):
"""Create context menu actions"""
actions = []
@@ -459,7 +459,7 @@ class DirView(QTreeView):
"""Update context menu"""
self.menu.clear()
add_actions(self.menu, self.create_context_menu_actions())
#---- Events
def viewportEvent(self, event):
"""Reimplement Qt method"""
@@ -474,9 +474,9 @@ class DirView(QTreeView):
#
# Apparently, this is a bug from Qt itself.
self.executeDelayedItemsLayout()
return QTreeView.viewportEvent(self, event)
def contextMenuEvent(self, event):
"""Override Qt method"""
# Needed to handle not initialized menu.
@@ -520,11 +520,11 @@ class DirView(QTreeView):
self.directory_clicked(fname)
else:
self.open([fname])
def directory_clicked(self, dirname):
"""Directory was just clicked"""
pass
#---- Drag
def dragEnterEvent(self, event):
"""Drag and Drop - Enter event"""
@@ -537,7 +537,7 @@ class DirView(QTreeView):
event.accept()
else:
event.ignore()
def startDrag(self, dropActions):
"""Reimplement Qt Method - handle drag event"""
data = QMimeData()
@@ -545,7 +545,7 @@ class DirView(QTreeView):
drag = QDrag(self)
drag.setMimeData(data)
drag.exec_()
#---- File/Directory actions
@Slot()
def open(self, fnames=None):
@@ -557,7 +557,7 @@ class DirView(QTreeView):
self.parent_widget.sig_open_file.emit(fname)
else:
self.open_outside_spyder([fname])
@Slot()
def open_external(self, fnames=None):
"""Open files with default application"""
@@ -565,7 +565,7 @@ class DirView(QTreeView):
fnames = self.get_selected_filenames()
for fname in fnames:
self.open_outside_spyder([fname])
def open_outside_spyder(self, fnames):
"""Open file outside Spyder with the appropriate application
If this does not work, opening unknown file in Spyder, as text file"""
@@ -587,7 +587,7 @@ class DirView(QTreeView):
fnames = self.get_selected_filenames()
for fname in fnames:
self.sig_run.emit(fname)
def remove_tree(self, dirname):
"""Remove whole directory tree
Reimplemented in project explorer widget"""
@@ -600,7 +600,7 @@ class DirView(QTreeView):
if type(e).__name__ == "OSError":
error_path = to_text_string(e.filename)
shutil.rmtree(error_path, ignore_errors=True)
def delete_file(self, fname, multiple, yes_to_all):
"""Delete file"""
if multiple:
@@ -657,7 +657,7 @@ class DirView(QTreeView):
if yes_to_all is not None and not yes_to_all:
# Canceled
break
def convert_notebook(self, fname):
"""Convert an IPython notebook to a Python script in editor"""
try:
@@ -754,7 +754,7 @@ class DirView(QTreeView):
_("<b>Unable to move <i>%s</i></b>"
"<br><br>Error message:<br>%s"
) % (basename, to_text_string(error)))
def create_new_folder(self, current_path, title, subtitle, is_package):
"""Create new folder"""
if current_path is None:
@@ -793,13 +793,13 @@ class DirView(QTreeView):
title = _('New folder')
subtitle = _('Folder name:')
self.create_new_folder(basedir, title, subtitle, is_package=False)
def new_package(self, basedir):
"""New package"""
title = _('New package')
subtitle = _('Package name:')
self.create_new_folder(basedir, title, subtitle, is_package=True)
def create_new_file(self, current_path, title, filters, create_func):
"""Create new file
Returns True if successful"""
@@ -834,7 +834,7 @@ class DirView(QTreeView):
fname = self.create_new_file(basedir, title, filters, create_func)
if fname is not None:
self.open([fname])
def new_module(self, basedir):
"""New module"""
title = _("New module")
@@ -1042,36 +1042,36 @@ class DirView(QTreeView):
QMessageBox.critical(self, _("Error"),
_("""<b>Unable to find external program.</b><br><br>%s""")
% to_text_string(msg))
#----- Settings
def get_scrollbar_position(self):
"""Return scrollbar positions"""
return (self.horizontalScrollBar().value(),
self.verticalScrollBar().value())
def set_scrollbar_position(self, position):
"""Set scrollbar positions"""
# Scrollbars will be restored after the expanded state
self._scrollbar_positions = position
if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
self.restore_scrollbar_positions()
def restore_scrollbar_positions(self):
"""Restore scrollbar positions once tree is loaded"""
hor, ver = self._scrollbar_positions
self.horizontalScrollBar().setValue(hor)
self.verticalScrollBar().setValue(ver)
def get_expanded_state(self):
"""Return expanded state"""
self.save_expanded_state()
return self.__expanded_state
def set_expanded_state(self, state):
"""Set expanded state"""
self.__expanded_state = state
self.restore_expanded_state()
def save_expanded_state(self):
"""Save all items expanded state"""
model = self.model()
@@ -1099,7 +1099,7 @@ class DirView(QTreeView):
self.setExpanded(self.get_index(path), True)
if not self.__expanded_state:
self.fsmodel.directoryLoaded.disconnect(self.restore_directory_state)
def follow_directories_loaded(self, fname):
"""Follow directories loaded during startup"""
if self._to_be_loaded is None:
@@ -1123,7 +1123,7 @@ class DirView(QTreeView):
self.restore_directory_state)
self.fsmodel.directoryLoaded.connect(
self.follow_directories_loaded)
def filter_directories(self):
"""Filter the directories to show"""
index = self.get_index('.spyproject')
@@ -1137,7 +1137,7 @@ class ProxyModel(QSortFilterProxyModel):
self.root_path = None
self.path_list = []
self.setDynamicSortFilter(True)
def setup_filter(self, root_path, path_list):
"""Setup proxy model filter parameters"""
self.root_path = osp.normpath(to_text_string(root_path))
@@ -1180,18 +1180,18 @@ class FilteredDirView(DirView):
self.proxymodel = None
self.setup_proxy_model()
self.root_path = None
#---- Model
def setup_proxy_model(self):
"""Setup proxy model"""
self.proxymodel = ProxyModel(self)
self.proxymodel.setSourceModel(self.fsmodel)
def install_model(self):
"""Install proxy model"""
if self.root_path is not None:
self.setModel(self.proxymodel)
def set_root_path(self, root_path):
"""Set root path"""
self.root_path = root_path
@@ -1199,20 +1199,20 @@ class FilteredDirView(DirView):
index = self.fsmodel.setRootPath(root_path)
self.proxymodel.setup_filter(self.root_path, [])
self.setRootIndex(self.proxymodel.mapFromSource(index))
def get_index(self, filename):
"""Return index associated with filename"""
index = self.fsmodel.index(filename)
if index.isValid() and index.model() is self.fsmodel:
return self.proxymodel.mapFromSource(index)
def set_folder_names(self, folder_names):
"""Set folder names"""
assert self.root_path is not None
path_list = [osp.join(self.root_path, dirname)
for dirname in folder_names]
self.proxymodel.setup_filter(self.root_path, path_list)
def get_filename(self, index):
"""Return filename from index"""
if index:
@@ -1236,7 +1236,7 @@ class ExplorerTreeWidget(DirView):
set_previous_enabled = Signal(bool)
set_next_enabled = Signal(bool)
sig_open_dir = Signal(str)
def __init__(self, parent=None, show_cd_only=None):
DirView.__init__(self, parent)
@@ -1249,7 +1249,7 @@ class ExplorerTreeWidget(DirView):
self.menu = None
self.common_actions = None
# Enable drag events
self.setDragEnabled(True)
@@ -1281,7 +1281,7 @@ class ExplorerTreeWidget(DirView):
self.set_current_folder(self.__last_folder)
elif self.__original_root_index is not None:
self.setRootIndex(self.__original_root_index)
#---- Refreshing widget
def set_current_folder(self, folder):
"""Set current folder and return associated model index"""
@@ -1292,7 +1292,7 @@ class ExplorerTreeWidget(DirView):
self.__original_root_index = self.rootIndex()
self.setRootIndex(index)
return index
def get_current_folder(self):
return self.__last_folder
@@ -1311,12 +1311,12 @@ class ExplorerTreeWidget(DirView):
self.histindex < len(self.history)-1)
# Disable the view of .spyproject.
self.filter_directories()
#---- Events
def directory_clicked(self, dirname):
"""Directory was just clicked"""
self.chdir(directory=dirname)
#---- Files/Directories Actions
@Slot()
def go_to_parent_directory(self):
@@ -1334,7 +1334,7 @@ class ExplorerTreeWidget(DirView):
"""Return to next directory"""
self.histindex += 1
self.chdir(browsing_history=True)
def update_history(self, directory):
"""Update browse history"""
try:
@@ -1344,7 +1344,7 @@ class ExplorerTreeWidget(DirView):
except Exception:
user_directory = get_home_dir()
self.chdir(directory=user_directory, browsing_history=True)
def chdir(self, directory=None, browsing_history=False):
"""Set directory as working directory"""
if directory is not None:
@@ -1485,7 +1485,7 @@ class FileExplorerTest(QWidget):
else:
self.directory = osp.dirname(osp.abspath(__file__))
vlayout.addWidget(self.explorer)
hlayout1 = QHBoxLayout()
vlayout.addLayout(hlayout1)
label = QLabel("<b>Open file:</b>")
@@ -1494,7 +1494,7 @@ class FileExplorerTest(QWidget):
self.label1 = QLabel()
hlayout1.addWidget(self.label1)
self.explorer.sig_open_file.connect(self.label1.setText)
hlayout2 = QHBoxLayout()
vlayout.addLayout(hlayout2)
label = QLabel("<b>Open dir:</b>")
@@ -1503,7 +1503,7 @@ class FileExplorerTest(QWidget):
self.label2 = QLabel()
hlayout2.addWidget(self.label2)
self.explorer.open_dir.connect(self.label2.setText)
hlayout3 = QHBoxLayout()
vlayout.addLayout(hlayout3)
label = QLabel("<b>Option changed:</b>")
+1 -1
Ver Arquivo
@@ -3645,7 +3645,7 @@ if ( !jQuery.support.submitBubbles ) {
});
// return undefined since we don't need an event listener
},
postDispatch: function( event ) {
// If form was submitted by the user, bubble the event up the tree
if ( event._submit_bubble ) {
+3 -3
Ver Arquivo
@@ -30,7 +30,7 @@ $(document).ready(function () {
"SVG": {
blacker: 1
},
{% if platform == 'win32' %}
// Change math preview size so that it doesn't look too big while
// redendered
@@ -42,7 +42,7 @@ $(document).ready(function () {
}
{% endif %}
});
// MathJax Hooks
// -------------
// Put here any code that needs to be evaluated after MathJax has been
@@ -51,7 +51,7 @@ $(document).ready(function () {
// Eliminate unnecessary margin-bottom for inline math
$('span.math svg').css('margin-bottom', '0px');
});
{% if platform == 'win32' %}
// Windows fix
// -----------
+2 -2
Ver Arquivo
@@ -15,7 +15,7 @@ $(document).ready(function () {
// Remove anchor header links.
// They're used by Sphinx to create crossrefs, so we don't need them
$('a.headerlink').remove();
// If the first child in the docstring div is a section, change its class
// to title. This means that the docstring has a real title and we need
// to use it.
@@ -24,7 +24,7 @@ $(document).ready(function () {
if( first_doc_child.is('div.section') && $('div.title').length == 0 ) {
first_doc_child.removeClass('section').addClass('title');
};
// Change docstring headers from h1 to h2
// It can only be an h1 and that's the page title
// Taken from http://forum.jquery.com/topic/how-to-replace-h1-h2
+6 -6
Ver Arquivo
@@ -95,7 +95,7 @@ def generate_context(name='', argspec='', note='', math=False, collapse=False,
img_path='', css_path=CSS_PATH):
"""
Generate the html_context dictionary for our Sphinx conf file.
This is a set of variables to be passed to the Jinja template engine and
that are used to control how the webpage is rendered in connection with
Sphinx
@@ -142,7 +142,7 @@ def generate_context(name='', argspec='', note='', math=False, collapse=False,
'right_sphinx_version': '' if sphinx.__version__ < "1.1" else 'true',
'platform': sys.platform
}
return context
@@ -183,7 +183,7 @@ def sphinxify(docstring, context, buildername='html'):
# docstrings
if context['right_sphinx_version'] and context['math_on']:
docstring = docstring.replace('\\\\', '\\\\\\\\')
# Add a class to several characters on the argspec. This way we can
# highlight them using css, in a similar way to what IPython does.
# NOTE: Before doing this, we escape common html chars so that they
@@ -197,7 +197,7 @@ def sphinxify(docstring, context, buildername='html'):
doc_file = codecs.open(rst_name, 'w', encoding='utf-8')
doc_file.write(docstring)
doc_file.close()
temp_confdir = False
if temp_confdir:
# TODO: This may be inefficient. Find a faster way to do it.
@@ -248,14 +248,14 @@ def generate_configuration(directory):
directory : str
Base directory to use
"""
# conf.py file for Sphinx
conf = osp.join(get_module_source_path('spyder.plugins.help.utils'),
'conf.py')
# Docstring layout page (in Jinja):
layout = osp.join(osp.join(CONFDIR_PATH, 'templates'), 'layout.html')
os.makedirs(osp.join(directory, 'templates'))
os.makedirs(osp.join(directory, 'static'))
shutil.copy(conf, directory)
+2 -2
Ver Arquivo
@@ -23,7 +23,7 @@
<link rel="stylesheet" href="file:///{{css_path}}/default.css" type="text/css" />
<link rel="stylesheet" href="file:///{{css_path}}/pygments.css" type="text/css" />
<script type="text/javascript" src="file:///{{jquery_path}}/jquery.js"></script>
{% if right_sphinx_version and math_on %}
{# DON'T try to load MathJax from the net. It's slow and sometimes gives
errors. See this thread for more info:
@@ -73,7 +73,7 @@
{% endif %}
{% endif %}
{# Docstring text #}
<div class="docstring">
{% block body %}{% endblock %}
+3 -3
Ver Arquivo
@@ -40,7 +40,7 @@ try:
import imp
imp.find_module('h5py')
import numpy as np
def load_hdf5(filename):
import h5py
def get_group(group):
@@ -53,7 +53,7 @@ try:
contents[name] = get_group(obj)
# other objects such as links are ignored
return contents
try:
f = h5py.File(filename, 'r')
contents = get_group(f)
@@ -61,7 +61,7 @@ try:
return contents, None
except Exception as error:
return None, str(error)
def save_hdf5(data, filename):
import h5py
try:
+11 -11
Ver Arquivo
@@ -231,16 +231,16 @@ class IPythonConsole(SpyderPluginWidget):
self.create_new_client(give_focus=True)
else:
self.dockwidget.hide()
#------ SpyderPluginWidget API --------------------------------------------
def get_plugin_title(self):
"""Return widget title"""
return _('IPython console')
def get_plugin_icon(self):
"""Return widget icon"""
return ima.icon('ipython_console')
def get_focus_widget(self):
"""
Return the widget to give focus to when
@@ -361,11 +361,11 @@ class IPythonConsole(SpyderPluginWidget):
_("Connect to an existing kernel"), None, None,
_("Open a new IPython console connected to an existing kernel"),
triggered=self.create_client_for_kernel)
rename_tab_action = create_action(self, _("Rename tab"),
icon=ima.icon('rename'),
triggered=self.tab_name_editor)
# Add the action to the 'Consoles' menu on the main window
main_consoles_menu = self.main.consoles_menu_actions
main_consoles_menu.insert(0, create_client_action)
@@ -420,7 +420,7 @@ class IPythonConsole(SpyderPluginWidget):
for client in self.get_clients():
if widget is client or widget is client.get_control():
return client
def get_current_client(self):
"""Return the currently selected client"""
client = self.tabwidget.currentWidget()
@@ -920,13 +920,13 @@ class IPythonConsole(SpyderPluginWidget):
self.main.historylog.add_history(client.history_filename)
client.append_to_history.connect(
self.main.historylog.append_to_history)
# Set font for client
client.set_font( self.get_plugin_font() )
# Connect focus signal to client's control widget
control.focus_changed.connect(lambda: self.focus_changed.emit())
shellwidget.sig_change_cwd.connect(self.set_working_directory)
# Update the find widget if focus changes between control and
@@ -1254,7 +1254,7 @@ class IPythonConsole(SpyderPluginWidget):
self.activateWindow()
widget.get_control().setFocus()
self.update_tabs_text()
def move_tab(self, index_from, index_to):
"""
Move tab (tabs themselves have already been moved by the tabwidget)
@@ -1423,7 +1423,7 @@ class IPythonConsole(SpyderPluginWidget):
new_slave_ord = ord(cl.id_['str_id'])
if new_slave_ord > slave_ord:
slave_ord = new_slave_ord
# If we couldn't find a client with the same connection file,
# it means this is a new master client
if master_id is None:
+13 -13
Ver Arquivo
@@ -25,13 +25,13 @@ from spyder.widgets.browser import WebBrowser
class PydocServer(QThread):
"""Pydoc server"""
server_started = Signal()
def __init__(self, port=7464):
QThread.__init__(self)
self.port = port
self.server = None
self.complete = False
def run(self):
import pydoc
if PY3:
@@ -51,10 +51,10 @@ class PydocServer(QThread):
def callback(self, server):
self.server = server
self.server_started.emit()
def completer(self):
self.complete = True
def quit_server(self):
if PY3:
# Python 3
@@ -71,35 +71,35 @@ class PydocBrowser(WebBrowser):
pydoc widget
"""
DEFAULT_PORT = 30128
def __init__(self, parent, options_button=None):
WebBrowser.__init__(self, parent, options_button=options_button)
self.server = None
self.port = None
def initialize(self):
"""Start pydoc server"""
QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
QApplication.processEvents()
self.start_server()
# Initializing continues in `initialize_continued` method...
def initialize_continued(self):
"""Load home page"""
self.go_home()
QApplication.restoreOverrideCursor()
def is_server_running(self):
"""Return True if pydoc server is already running"""
return self.server is not None
def closeEvent(self, event):
if self.is_server_running():
self.server.quit_server()
# while not self.server.complete: #XXX Is it really necessary?
# pass
event.accept()
#------ Public API -----------------------------------------------------
def start_server(self):
"""Start pydoc server"""
@@ -117,18 +117,18 @@ class PydocBrowser(WebBrowser):
def get_label(self):
"""Return address label text"""
return _("Module or package:")
def reload(self):
"""Reload page"""
self.start_server()
WebBrowser.reload(self)
def text_to_url(self, text):
"""Convert text address into QUrl object"""
if text.startswith('/'):
text = text[1:]
return QUrl(self.home_url.toString()+text+'.html')
def url_to_text(self, url):
"""Convert QUrl object to displayed text in combo box"""
return osp.splitext(to_text_string(url.path()))[0][1:]
+2 -2
Ver Arquivo
@@ -25,9 +25,9 @@ class PythonCFM(object):
match = re.match(r'[\ ]*%s ([a-zA-Z0-9_]*)[\ ]*[\(|\:]' % statmt, text)
if match is not None:
return match.group(1)
def get_function_name(self, text):
return self.__get_name('def', text)
def get_class_name(self, text):
return self.__get_name('class', text)
+41 -41
Ver Arquivo
@@ -66,13 +66,13 @@ class ProfilerWidget(QWidget):
DATAPATH = get_conf_path('profiler.results')
VERSION = '0.0.1'
redirect_stdio = Signal(bool)
def __init__(self, parent, max_entries=100, options_button=None,
text_color=None):
QWidget.__init__(self, parent)
self.setWindowTitle("Profiler")
self.output = None
self.error_output = None
@@ -81,9 +81,9 @@ class ProfilerWidget(QWidget):
self._last_wdir = None
self._last_args = None
self._last_pythonpath = None
self.filecombo = PythonModulesComboBox(self)
self.start_button = create_toolbutton(self, icon=ima.icon('run'),
text=_("Profile"),
tip=_("Run profiler"),
@@ -123,7 +123,7 @@ class ProfilerWidget(QWidget):
triggered=lambda dD:
self.datatree.change_view(1),
tip=_('Expand one level down'))
self.save_button = create_toolbutton(self, text_beside_icon=True,
text=_("Save data"),
icon=ima.icon('filesave'),
@@ -157,13 +157,13 @@ class ProfilerWidget(QWidget):
hlayout2.addWidget(self.save_button)
hlayout2.addWidget(self.load_button)
hlayout2.addWidget(self.clear_button)
layout = QVBoxLayout()
layout.addLayout(hlayout1)
layout.addLayout(hlayout2)
layout.addWidget(self.datatree)
self.setLayout(layout)
self.process = None
self.set_running_state(False)
self.start_button.setEnabled(False)
@@ -182,7 +182,7 @@ class ProfilerWidget(QWidget):
self.datelabel.setText(text)
else:
pass # self.show_data()
def save_data(self):
"""Save data"""
title = _( "Save profiler result")
@@ -191,7 +191,7 @@ class ProfilerWidget(QWidget):
_("Profiler result")+" (*.Result)")
if filename:
self.datatree.save_data(filename)
def compare(self):
filename, _selfilter = getopenfilename(
self, _("Select script to compare"),
@@ -223,7 +223,7 @@ class ProfilerWidget(QWidget):
if wdir is None:
wdir = osp.dirname(filename)
self.start(wdir, args, pythonpath)
def select_file(self):
self.redirect_stdio.emit(False)
filename, _selfilter = getopenfilename(
@@ -232,12 +232,12 @@ class ProfilerWidget(QWidget):
self.redirect_stdio.emit(True)
if filename:
self.analyze(filename)
def show_log(self):
if self.output:
TextEditor(self.output, title=_("Profiler output"),
readonly=True, size=(700, 500), parent=self).exec_()
def show_errorlog(self):
if self.error_output:
TextEditor(self.error_output, title=_("Profiler output"),
@@ -258,9 +258,9 @@ class ProfilerWidget(QWidget):
self._last_wdir = wdir
self._last_args = args
self._last_pythonpath = pythonpath
self.datelabel.setText(_('Profiling, please wait...'))
self.process = QProcess(self)
self.process.setProcessChannelMode(QProcess.SeparateChannels)
self.process.setWorkingDirectory(wdir)
@@ -280,11 +280,11 @@ class ProfilerWidget(QWidget):
envName, separator, envValue = envItem.partition('=')
processEnvironment.insert(envName, envValue)
self.process.setProcessEnvironment(processEnvironment)
self.output = ''
self.error_output = ''
self.stopped = False
p_args = ['-m', 'cProfile', '-o', self.DATAPATH]
if os.name == 'nt':
# On Windows, one has to replace backslashes by slashes to avoid
@@ -300,7 +300,7 @@ class ProfilerWidget(QWidget):
# py2exe distribution
executable = "python.exe"
self.process.start(executable, p_args)
running = self.process.waitForStarted()
self.set_running_state(running)
if not running:
@@ -315,7 +315,7 @@ class ProfilerWidget(QWidget):
def set_running_state(self, state=True):
self.start_button.setEnabled(not state)
self.stop_button.setEnabled(state)
def read_output(self, error=False):
if error:
self.process.setReadChannel(QProcess.StandardError)
@@ -332,7 +332,7 @@ class ProfilerWidget(QWidget):
self.error_output += text
else:
self.output += text
def finished(self, exit_code, exit_status):
self.set_running_state(False)
self.show_errorlog() # If errors occurred, show them.
@@ -340,13 +340,13 @@ class ProfilerWidget(QWidget):
# FIXME: figure out if show_data should be called here or
# as a signal from the combobox
self.show_data(justanalyzed=True)
def kill_if_running(self):
if self.process is not None:
if self.process.state() == QProcess.Running:
self.process.kill()
self.process.waitForFinished()
def show_data(self, justanalyzed=False):
if not justanalyzed:
self.output = None
@@ -405,7 +405,7 @@ def gettime_s(text):
class TreeWidgetItem( QTreeWidgetItem ):
def __init__(self, parent=None):
QTreeWidgetItem.__init__(self, parent)
def __lt__(self, otherItem):
column = self.treeWidget().sortColumn()
try:
@@ -414,7 +414,7 @@ class TreeWidgetItem( QTreeWidgetItem ):
t1 = gettime_s(otherItem.text(column))
if t0 is not None and t1 is not None:
return t0 > t1
return float( self.text(column) ) > float( otherItem.text(column) )
except ValueError:
return self.text(column) > otherItem.text(column)
@@ -468,7 +468,7 @@ class ProfilerDataTree(QTreeWidget):
def set_item_data(self, item, filename, line_number):
"""Set tree item user data: filename (string) and line_number (int)"""
set_item_user_text(item, '%s%s%d' % (filename, self.SEP, line_number))
def get_item_data(self, item):
"""Get tree item user data: (filename, line_number)"""
filename, line_number_str = get_item_user_text(item).split(self.SEP)
@@ -490,7 +490,7 @@ class ProfilerDataTree(QTreeWidget):
except (OSError, IOError):
return
self.profdata = stats_indi[0]
if self.compare_file is not None:
try:
stats_indi.append(pstats.Stats(self.compare_file))
@@ -504,15 +504,15 @@ class ProfilerDataTree(QTreeWidget):
self.profdata.calc_callees()
self.stats1 = stats_indi
self.stats = stats_indi[0].stats
def compare(self,filename):
self.hide_diff_cols(False)
self.compare_file = filename
def hide_diff_cols(self, hide):
for i in (2,4,6):
self.setColumnHidden(i, hide)
def save_data(self, filename):
""""""
self.stats1[0].dump_stats(filename)
@@ -526,7 +526,7 @@ class ProfilerDataTree(QTreeWidget):
# This skips the profiler function at the top of the list
# it does only occur in Python 3
return func
def find_callees(self, parent):
"""Find all functions called by (parent) function."""
# FIXME: This implementation is very inneficient, because it
@@ -657,7 +657,7 @@ class ProfilerDataTree(QTreeWidget):
'(including sub-functions)'))
child_item.setData(1, Qt.DisplayRole, cum_time)
child_item.setTextAlignment(1, Qt.AlignRight)
child_item.setData(2, Qt.DisplayRole, cum_time_dif[0])
child_item.setForeground(2, QColor(cum_time_dif[1]))
child_item.setTextAlignment(2, Qt.AlignLeft)
@@ -667,7 +667,7 @@ class ProfilerDataTree(QTreeWidget):
child_item.setData(3, Qt.DisplayRole, loc_time)
child_item.setTextAlignment(3, Qt.AlignRight)
child_item.setData(4, Qt.DisplayRole, loc_time_dif[0])
child_item.setForeground(4, QColor(loc_time_dif[1]))
child_item.setTextAlignment(4, Qt.AlignLeft)
@@ -677,7 +677,7 @@ class ProfilerDataTree(QTreeWidget):
child_item.setData(5, Qt.DisplayRole, total_calls)
child_item.setTextAlignment(5, Qt.AlignRight)
child_item.setData(6, Qt.DisplayRole, total_calls_dif[0])
child_item.setForeground(6, QColor(total_calls_dif[1]))
child_item.setTextAlignment(6, Qt.AlignLeft)
@@ -697,16 +697,16 @@ class ProfilerDataTree(QTreeWidget):
child_item.setChildIndicatorPolicy(child_item.ShowIndicator)
self.items_to_be_shown[id(child_item)] = callees
self.item_depth -= 1
def item_activated(self, item):
filename, line_number = self.get_item_data(item)
self.sig_edit_goto.emit(filename, line_number, '')
def item_expanded(self, item):
if item.childCount() == 0 and id(item) in self.items_to_be_shown:
callees = self.items_to_be_shown[id(item)]
self.populate_tree(item, callees)
def is_recursive(self, child_item):
"""Returns True is a function is a descendant of itself."""
ancestor = child_item.parent()
@@ -720,11 +720,11 @@ class ProfilerDataTree(QTreeWidget):
else:
ancestor = ancestor.parent()
return False
def get_top_level_items(self):
"""Iterate over top level items"""
return [self.topLevelItem(_i) for _i in range(self.topLevelItemCount())]
def get_items(self, maxlevel):
"""Return all items with a level <= `maxlevel`"""
itemlist = []
@@ -740,7 +740,7 @@ class ProfilerDataTree(QTreeWidget):
if maxlevel > 0:
add_to_itemlist(tlitem, maxlevel=maxlevel)
return itemlist
def change_view(self, change_in_depth):
"""Change the view depth by expand or collapsing all same-level nodes"""
self.current_view_depth += change_in_depth
@@ -750,7 +750,7 @@ class ProfilerDataTree(QTreeWidget):
if self.current_view_depth > 0:
for item in self.get_items(maxlevel=self.current_view_depth-1):
item.setExpanded(True)
#==============================================================================
# Tests
@@ -793,7 +793,7 @@ def test():
f.write("# -*- coding: utf-8 -*-" + "\n\n")
f.write(primes_sc + "\n\n")
f.write("primes(100000)")
app = qapplication(test_time=5)
widget = ProfilerWidget(None)
widget.resize(800, 600)
+1 -1
Ver Arquivo
@@ -29,7 +29,7 @@ from spyder.plugins.explorer.widgets import FilteredDirView
class ExplorerTreeWidget(FilteredDirView):
"""Explorer tree widget"""
sig_delete_project = Signal()
def __init__(self, parent, show_hscrollbar=True):
@@ -175,9 +175,9 @@ class ProjectDialog(QDialog):
else:
self.button_create.setEnabled(False)
path = self.location
self.text_location.setText(path)
def create_project(self):
"""Create project."""
packages = ['python={0}'.format(self.combo_python_version.currentText())]
@@ -186,7 +186,7 @@ class ProjectDialog(QDialog):
self.combo_project_type.currentText(),
packages)
self.accept()
def test():
"""Local test."""
+31 -31
Ver Arquivo
@@ -63,7 +63,7 @@ class ResultsTree(OneColumnTree):
self.results = None
self.data = None
self.set_title('')
def activated(self, item):
"""Double-click event"""
data = self.data.get(id(item))
@@ -74,16 +74,16 @@ class ResultsTree(OneColumnTree):
def clicked(self, item):
"""Click event"""
self.activated(item)
def clear_results(self):
self.clear()
self.set_title('')
def set_results(self, filename, results):
self.filename = filename
self.results = results
self.refresh()
def refresh(self):
title = _('Results for ')+self.filename
self.set_title(title)
@@ -149,13 +149,13 @@ class PylintWidget(QWidget):
DATAPATH = get_conf_path('pylint.results')
VERSION = '1.1.0'
redirect_stdio = Signal(bool)
def __init__(self, parent, max_entries=100, options_button=None,
text_color=None, prevrate_color=None):
QWidget.__init__(self, parent)
self.setWindowTitle("Pylint")
self.output = None
self.error_output = None
@@ -173,7 +173,7 @@ class PylintWidget(QWidget):
pass
self.filecombo = PythonModulesComboBox(self)
self.start_button = create_toolbutton(self, icon=ima.icon('run'),
text=_("Analyze"),
tip=_("Run analysis"),
@@ -198,7 +198,7 @@ class PylintWidget(QWidget):
tip=_("Complete output"),
triggered=self.show_log)
self.treewidget = ResultsTree(self)
hlayout1 = QHBoxLayout()
hlayout1.addWidget(self.filecombo)
hlayout1.addWidget(browse_button)
@@ -213,13 +213,13 @@ class PylintWidget(QWidget):
hlayout2.addWidget(self.datelabel)
hlayout2.addStretch()
hlayout2.addWidget(self.log_button)
layout = QVBoxLayout()
layout.addLayout(hlayout1)
layout.addLayout(hlayout2)
layout.addWidget(self.treewidget)
self.setLayout(layout)
self.process = None
self.set_running_state(False)
self.show_data()
@@ -253,15 +253,15 @@ class PylintWidget(QWidget):
self.redirect_stdio.emit(True)
if filename:
self.analyze(filename)
def remove_obsolete_items(self):
"""Removing obsolete items"""
self.rdata = [(filename, data) for filename, data in self.rdata
if is_module_or_package(filename)]
def get_filenames(self):
return [filename for filename, _data in self.rdata]
def get_data(self, filename):
filename = osp.abspath(filename)
for index, (fname, data) in enumerate(self.rdata):
@@ -269,7 +269,7 @@ class PylintWidget(QWidget):
return index, data
else:
return None, None
def set_data(self, filename, data):
filename = osp.abspath(filename)
index, _data = self.get_data(filename)
@@ -277,7 +277,7 @@ class PylintWidget(QWidget):
self.rdata.pop(index)
self.rdata.insert(0, (filename, data))
self.save()
def save(self):
while len(self.rdata) > self.max_entries:
self.rdata.pop(-1)
@@ -292,7 +292,7 @@ class PylintWidget(QWidget):
@Slot()
def start(self):
filename = to_text_string(self.filecombo.currentText())
self.process = QProcess(self)
self.process.setProcessChannelMode(QProcess.SeparateChannels)
self.process.setWorkingDirectory(osp.dirname(filename))
@@ -302,10 +302,10 @@ class PylintWidget(QWidget):
self.process.finished.connect(lambda ec, es=QProcess.ExitStatus:
self.finished(ec, es))
self.stop_button.clicked.connect(self.process.kill)
self.output = ''
self.error_output = ''
plver = PYLINT_VER
if plver is not None:
p_args = ['-m', 'pylint', '--output-format=text']
@@ -320,17 +320,17 @@ class PylintWidget(QWidget):
else:
p_args = [osp.basename(filename)]
self.process.start(sys.executable, p_args)
running = self.process.waitForStarted()
self.set_running_state(running)
if not running:
QMessageBox.critical(self, _("Error"),
_("Process failed to start"))
def set_running_state(self, state=True):
self.start_button.setEnabled(not state)
self.stop_button.setEnabled(state)
def read_output(self, error=False):
if error:
self.process.setReadChannel(QProcess.StandardError)
@@ -347,7 +347,7 @@ class PylintWidget(QWidget):
self.error_output += text
else:
self.output += text
def finished(self, exit_code, exit_status):
self.set_running_state(False)
if not self.output:
@@ -355,11 +355,11 @@ class PylintWidget(QWidget):
QMessageBox.critical(self, _("Error"), self.error_output)
print("pylint error:\n\n" + self.error_output, file=sys.stderr)
return
# Convention, Refactor, Warning, Error
results = {'C:': [], 'R:': [], 'W:': [], 'E:': []}
txt_module = '************* Module '
module = '' # Should not be needed - just in case something goes wrong
for line in self.output.splitlines():
if line.startswith(txt_module):
@@ -383,7 +383,7 @@ class PylintWidget(QWidget):
message = line[i2+1:]
item = (module, line_nb, message, msg_id)
results[line[0]+':'].append(item)
# Rate
rate = None
txt_rate = 'Your code has been rated at '
@@ -392,7 +392,7 @@ class PylintWidget(QWidget):
i_rate_end = self.output.find('/10', i_rate)
if i_rate_end > 0:
rate = self.output[i_rate+len(txt_rate):i_rate_end]
# Previous run
previous = ''
if rate is not None:
@@ -401,19 +401,19 @@ class PylintWidget(QWidget):
if i_prun > 0:
i_prun_end = self.output.find('/10', i_prun)
previous = self.output[i_prun+len(txt_prun):i_prun_end]
filename = to_text_string(self.filecombo.currentText())
self.set_data(filename, (time.localtime(), rate, previous, results))
self.output = self.error_output + self.output
self.show_data(justanalyzed=True)
def kill_if_running(self):
if self.process is not None:
if self.process.state() == QProcess.Running:
self.process.kill()
self.process.waitForFinished()
def show_data(self, justanalyzed=False):
if not justanalyzed:
self.output = None
@@ -423,7 +423,7 @@ class PylintWidget(QWidget):
filename = to_text_string(self.filecombo.currentText())
if not filename:
return
_index, data = self.get_data(filename)
if data is None:
text = _('Source code has not been rated yet.')
@@ -25,7 +25,7 @@ def test_get_settings(monkeypatch):
if option == 'remote1': return 'remote1val'
if option == 'remote2': return 'remote2val'
if option == 'dataframe_format': return '3d'
monkeypatch.setattr(VariableExplorer, 'CONF_SECTION', 'sect')
monkeypatch.setattr('spyder.plugins.variableexplorer.plugin.REMOTE_SETTINGS',
['remote1', 'remote2'])
@@ -136,7 +136,7 @@ class ArrayModel(QAbstractTableModel):
self.color_func = np.abs
else:
self.color_func = np.real
# Backgroundcolor settings
huerange = [.66, .99] # Hue
self.sat = .7 # Saturation
@@ -145,11 +145,11 @@ class ArrayModel(QAbstractTableModel):
self._data = data
self._format = format
self.total_rows = self._data.shape[0]
self.total_cols = self._data.shape[1]
size = self.total_rows * self.total_cols
try:
self.vmin = np.nanmin(self.color_func(data))
self.vmax = np.nanmax(self.color_func(data))
@@ -164,7 +164,7 @@ class ArrayModel(QAbstractTableModel):
self.hue0 = None
self.dhue = None
self.bgcolor_enabled = False
# Use paging when the total size, number of rows or number of
# columns is too large
if size > LARGE_SIZE:
@@ -179,16 +179,16 @@ class ArrayModel(QAbstractTableModel):
self.cols_loaded = self.COLS_TO_LOAD
else:
self.cols_loaded = self.total_cols
def get_format(self):
"""Return current format"""
# Avoid accessing the private attribute _format from outside
return self._format
def get_data(self):
"""Return data"""
return self._data
def set_format(self, format):
"""Change display format"""
self._format = format
@@ -207,7 +207,7 @@ class ArrayModel(QAbstractTableModel):
return self.total_rows
else:
return self.rows_loaded
def can_fetch_more(self, rows=False, columns=False):
if rows:
if self.total_rows > self.rows_loaded:
@@ -338,7 +338,7 @@ class ArrayModel(QAbstractTableModel):
return Qt.ItemIsEnabled
return Qt.ItemFlags(QAbstractTableModel.flags(self, index)|
Qt.ItemIsEditable)
def headerData(self, section, orientation, role=Qt.DisplayRole):
"""Set header data"""
if role != Qt.DisplayRole:
@@ -416,7 +416,7 @@ class ArrayView(QTableView):
lambda val: self.load_more_data(val, columns=True))
self.verticalScrollBar().valueChanged.connect(
lambda val: self.load_more_data(val, rows=True))
def load_more_data(self, value, rows=False, columns=False):
try:
@@ -484,7 +484,7 @@ class ArrayView(QTableView):
"""Reimplement Qt method"""
self.menu.popup(event.globalPos())
event.accept()
def keyPressEvent(self, event):
"""Reimplement Qt method"""
if event == QKeySequence.Copy:
@@ -504,7 +504,7 @@ class ArrayView(QTableView):
col_max = self.model().total_cols-1
if row_min == 0 and row_max == (self.model().rows_loaded-1):
row_max = self.model().total_rows-1
_data = self.model().get_data()
if PY3:
output = io.BytesIO()
@@ -548,7 +548,7 @@ class ArrayEditorWidget(QWidget):
self.model = ArrayModel(self.data, format=format, xlabels=xlabels,
ylabels=ylabels, readonly=readonly, parent=self)
self.view = ArrayView(self, self.model, data.dtype, data.shape)
btn_layout = QHBoxLayout()
btn_layout.setAlignment(Qt.AlignLeft)
btn = QPushButton(_( "Format"))
@@ -564,24 +564,24 @@ class ArrayEditorWidget(QWidget):
bgcolor.setEnabled(self.model.bgcolor_enabled)
bgcolor.stateChanged.connect(self.model.bgcolor)
btn_layout.addWidget(bgcolor)
layout = QVBoxLayout()
layout.addWidget(self.view)
layout.addLayout(btn_layout)
self.setLayout(layout)
def accept_changes(self):
"""Accept changes"""
for (i, j), value in list(self.model.changes.items()):
self.data[i, j] = value
if self.old_data_shape is not None:
self.data.shape = self.old_data_shape
def reject_changes(self):
"""Reject changes"""
if self.old_data_shape is not None:
self.data.shape = self.old_data_shape
def change_format(self):
"""Change display format"""
format, valid = QInputDialog.getText(self, _( 'Format'),
@@ -602,13 +602,13 @@ class ArrayEditor(QDialog):
"""Array Editor Dialog"""
def __init__(self, parent=None):
QDialog.__init__(self, parent)
# Destroying the C++ object right after closing the dialog box,
# otherwise it may be garbage-collected in another QThread
# (e.g. the editor's analysis thread in Spyder), thus leading to
# a segmentation fault on UNIX or an application crash on Windows
self.setAttribute(Qt.WA_DeleteOnClose)
self.data = None
self.arraywidget = None
self.stack = None
@@ -618,7 +618,7 @@ class ArrayEditor(QDialog):
# Values for 3d array editor
self.dim_indexes = [{}, {}, {}]
self.last_dim = 0 # Adjust this for changing the startup dimension
def setup_and_check(self, data, title='', readonly=False,
xlabels=None, ylabels=None):
"""
@@ -649,7 +649,7 @@ class ArrayEditor(QDialog):
arr = _("%s arrays") % data.dtype.name
self.error(_("%s are currently not supported") % arr)
return False
self.layout = QGridLayout()
self.setLayout(self.layout)
self.setWindowIcon(ima.icon('arredit'))
@@ -661,7 +661,7 @@ class ArrayEditor(QDialog):
title += ' (' + _('read only') + ')'
self.setWindowTitle(title)
self.resize(600, 500)
# Stack widget
self.stack = QStackedWidget(self)
if is_record_array:
@@ -754,10 +754,10 @@ class ArrayEditor(QDialog):
self.layout.addLayout(btn_layout, 2, 0)
self.setMinimumSize(400, 300)
# Make the dialog act as a window
self.setWindowFlags(Qt.Window)
return True
@Slot(QModelIndex, QModelIndex)
@@ -771,7 +771,7 @@ class ArrayEditor(QDialog):
def current_widget_changed(self, index):
self.arraywidget = self.stack.widget(index)
self.arraywidget.model.dataChanged.connect(self.save_and_close_enable)
def change_active_widget(self, index):
"""
This is implemented for handling negative values in index for
@@ -825,7 +825,7 @@ class ArrayEditor(QDialog):
for index in range(self.stack.count()):
self.stack.widget(index).accept_changes()
QDialog.accept(self)
def get_value(self):
"""Return modified array -- this is *not* a copy"""
# It is import to avoid accessing Qt C++ object as it has probably
@@ -128,7 +128,7 @@ class DataFrameModel(QAbstractTableModel):
self._format = format
self.complex_intran = None
self.display_error_idxs = []
self.total_rows = self.df.shape[0]
self.total_cols = self.df.shape[1]
size = self.total_rows * self.total_cols
@@ -106,7 +106,7 @@ def get_color(value, alpha):
class ContentsWidget(QWidget):
"""Import wizard contents widget"""
asDataChanged = Signal(bool)
def __init__(self, parent, text):
QWidget.__init__(self, parent)
@@ -23,10 +23,10 @@ class DialogKeeper(QObject):
QObject.__init__(self)
self.dialogs = {}
self.namespace = None
def set_namespace(self, namespace):
self.namespace = namespace
def create_dialog(self, dialog, refname, func):
self.dialogs[id(dialog)] = dialog, refname, func
dialog.accepted.connect(
@@ -36,12 +36,12 @@ class DialogKeeper(QObject):
dialog.show()
dialog.activateWindow()
dialog.raise_()
def editor_accepted(self, dialog_id):
dialog, refname, func = self.dialogs[dialog_id]
self.namespace[refname] = func(dialog)
self.dialogs.pop(dialog_id)
def editor_rejected(self, dialog_id):
self.dialogs.pop(dialog_id)
@@ -52,7 +52,7 @@ def create_dialog(obj, obj_name):
"""Creates the editor dialog and returns a tuple (dialog, func) where func
is the function to be called with the dialog instance as argument, after
quitting the dialog box
The role of this intermediate function is to allow easy monkey-patching.
(uschmitt suggested this indirection here so that he can monkey patch
oedit to show eMZed related data)
@@ -108,17 +108,17 @@ def oedit(obj, modal=True, namespace=None):
(if Cancel is pressed, return None)
The object 'obj' is a container
Supported container types:
dict, list, set, tuple, str/unicode or numpy.array
(instantiate a new QApplication if necessary,
so it can be called directly from the interpreter)
"""
# Local import
from spyder.utils.qthelpers import qapplication
app = qapplication()
if modal:
obj_name = ''
else:
@@ -130,12 +130,12 @@ def oedit(obj, modal=True, namespace=None):
obj = namespace[obj_name]
# keep QApplication reference alive in the Python interpreter:
namespace['__qapp__'] = app
result = create_dialog(obj, obj_name)
if result is None:
return
dialog, end_func = result
if modal:
if dialog.exec_():
return end_func(dialog)
@@ -80,7 +80,7 @@ def test_arrayeditor_format(qtbot):
qtbot.keyClick(dlg.arraywidget.view, Qt.Key_Down, modifier=Qt.ShiftModifier)
contents = dlg.arraywidget.view._sel_to_text(dlg.arraywidget.view.selectedIndexes())
assert contents == "1.000000000000000000e+00\n2.000000000000000000e+00\n"
def test_arrayeditor_with_string_array(qtbot):
arr = np.array(["kjrekrjkejr"])
@@ -29,16 +29,16 @@ class TextEditor(QDialog):
def __init__(self, text, title='', font=None, parent=None,
readonly=False, size=(400, 300)):
QDialog.__init__(self, parent)
# Destroying the C++ object right after closing the dialog box,
# otherwise it may be garbage-collected in another QThread
# (e.g. the editor's analysis thread in Spyder), thus leading to
# a segmentation fault on UNIX or an application crash on Windows
self.setAttribute(Qt.WA_DeleteOnClose)
self.text = None
self.btn_save_and_close = None
# Display text as unicode if it comes as bytes, so users see
# its right representation
if is_binary_string(text):
@@ -46,7 +46,7 @@ class TextEditor(QDialog):
text = to_text_string(text, 'utf8')
else:
self.is_binary = False
self.layout = QVBoxLayout()
self.setLayout(self.layout)
@@ -79,7 +79,7 @@ class TextEditor(QDialog):
# Make the dialog act as a window
self.setWindowFlags(Qt.Window)
self.setWindowIcon(ima.icon('edit'))
if title:
try:
+34 -34
Ver Arquivo
@@ -59,7 +59,7 @@ class ConfigPage(QWidget):
QWidget.__init__(self, parent)
self.apply_callback = apply_callback
self.is_modified = False
def initialize(self):
"""
Initialize configuration page:
@@ -68,27 +68,27 @@ class ConfigPage(QWidget):
"""
self.setup_page()
self.load_from_conf()
def get_name(self):
"""Return configuration page name"""
raise NotImplementedError
def get_icon(self):
"""Return configuration page icon (24x24)"""
raise NotImplementedError
def setup_page(self):
"""Setup configuration page widget"""
raise NotImplementedError
def set_modified(self, state):
self.is_modified = state
self.apply_button_enabled.emit(state)
def is_valid(self):
"""Return True if all widget contents are valid"""
raise NotImplementedError
def apply_changes(self):
"""Apply changes callback"""
if self.is_modified:
@@ -113,7 +113,7 @@ class ConfigPage(QWidget):
def load_from_conf(self):
"""Load settings from configuration file"""
raise NotImplementedError
def save_to_conf(self):
"""Save settings to configuration file"""
raise NotImplementedError
@@ -121,11 +121,11 @@ class ConfigPage(QWidget):
class ConfigDialog(QDialog):
"""Spyder configuration ('Preferences') dialog box"""
# Signals
check_settings = Signal()
size_change = Signal(QSize)
def __init__(self, parent=None):
QDialog.__init__(self, parent)
@@ -189,11 +189,11 @@ class ConfigDialog(QDialog):
def get_current_index(self):
"""Return current page index"""
return self.contents_widget.currentRow()
def set_current_index(self, index):
"""Set current page index"""
self.contents_widget.setCurrentRow(index)
def get_page(self, index=None):
"""Return page widget"""
if index is None:
@@ -201,7 +201,7 @@ class ConfigDialog(QDialog):
else:
widget = self.pages_widget.widget(index)
return widget.widget()
@Slot()
def accept(self):
"""Reimplement Qt method"""
@@ -211,7 +211,7 @@ class ConfigDialog(QDialog):
return
configpage.apply_changes()
QDialog.accept(self)
def button_clicked(self, button):
if button is self.apply_btn:
# Apply button was clicked
@@ -219,12 +219,12 @@ class ConfigDialog(QDialog):
if not configpage.is_valid():
return
configpage.apply_changes()
def current_page_changed(self, index):
widget = self.get_page(index)
self.apply_btn.setVisible(widget.apply_callback is not None)
self.apply_btn.setEnabled(widget.is_modified)
def add_page(self, widget):
self.check_settings.connect(widget.check_settings)
widget.show_this_page.connect(lambda row=self.contents_widget.count():
@@ -242,12 +242,12 @@ class ConfigDialog(QDialog):
item.setText(widget.get_name())
item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
item.setSizeHint(QSize(0, 25))
def check_all_settings(self):
"""This method is called to check all configuration page settings
after configuration dialog has been shown"""
self.check_settings.emit()
def resizeEvent(self, event):
"""
Reimplement Qt method to be able to save the widget's size from the
@@ -278,20 +278,20 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
self.changed_options = set()
self.restart_options = dict() # Dict to store name and localized text
self.default_button_group = None
def apply_settings(self, options):
raise NotImplementedError
def check_settings(self):
"""This method is called to check settings after configuration
dialog has been shown"""
pass
def set_modified(self, state):
ConfigPage.set_modified(self, state)
if not state:
self.changed_options = set()
def is_valid(self):
"""Return True if all widget contents are valid"""
for lineedit in self.lineedits:
@@ -304,7 +304,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
QMessageBox.Ok)
return False
return True
def load_from_conf(self):
"""Load settings from configuration file"""
for checkbox, (option, default) in list(self.checkboxes.items()):
@@ -435,7 +435,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
bold = cb_bold.isChecked()
italic = cb_italic.isChecked()
self.set_option(option, (color, bold, italic))
@Slot(str)
def has_been_modified(self, option):
self.set_modified(True)
@@ -459,7 +459,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
msg_info, QMessageBox.Ok)
checkbox.clicked.connect(show_message)
return checkbox
def create_radiobutton(self, text, option, default=NoDefault,
tip=None, msg_warning=None, msg_info=None,
msg_if_enabled=False, button_group=None,
@@ -486,7 +486,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
radiobutton.restart_required = restart
radiobutton.label_text = text
return radiobutton
def create_lineedit(self, text, option, default=NoDefault,
tip=None, alignment=Qt.Vertical, regex=None,
restart=False, word_wrap=True, placeholder=None):
@@ -532,7 +532,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
edit.restart_required = restart
edit.label_text = text
return widget
def create_browsedir(self, text, option, default=NoDefault, tip=None):
widget = self.create_lineedit(text, option, default,
alignment=Qt.Horizontal)
@@ -561,7 +561,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
directory = getexistingdirectory(self, title, basedir)
if directory:
edit.setText(directory)
def create_browsefile(self, text, option, default=NoDefault, tip=None,
filters=None):
widget = self.create_lineedit(text, option, default,
@@ -593,7 +593,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
filename, _selfilter = getopenfilename(self, title, basedir, filters)
if filename:
edit.setText(filename)
def create_spinbox(self, prefix, suffix, option, default=NoDefault,
min_=None, max_=None, step=None, tip=None):
widget = QWidget(self)
@@ -632,7 +632,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
widget.spinbox = spinbox
widget.setLayout(layout)
return widget
def create_coloredit(self, text, option, default=NoDefault, tip=None,
without_layout=False):
label = QLabel(text)
@@ -651,7 +651,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
widget = QWidget(self)
widget.setLayout(layout)
return widget
def create_scedit(self, text, option, default=NoDefault, tip=None,
without_layout=False):
label = QLabel(text)
@@ -679,7 +679,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
widget = QWidget(self)
widget.setLayout(layout)
return widget
def create_combobox(self, text, choices, option, default=NoDefault,
tip=None, restart=False):
"""choices: couples (name, key)"""
@@ -795,7 +795,7 @@ class SpyderConfigPage(ConfigPage, ConfigAccessMixin):
btn.clicked.connect(callback)
btn.clicked.connect(lambda checked=False, opt='': self.has_been_modified(opt))
return btn
def create_tab(self, *widgets):
"""Create simple tab widget page: widgets added in a vertical layout"""
widget = QWidget()
@@ -823,7 +823,7 @@ class GeneralConfigPage(SpyderConfigPage):
def get_name(self):
"""Configuration page name"""
return self.NAME
def get_icon(self):
"""Loads page icon named by self.ICON"""
return self.ICON
+1 -1
Ver Arquivo
@@ -203,7 +203,7 @@ class LayoutSettingsDialog(QDialog):
self.table.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.table.horizontalHeader().setStretchLastSection(True)
self.table.setColumnHidden(1, True)
# need to keep a reference for pyside not to segfault!
self._selection_model = self.table.selectionModel()
+20 -20
Ver Arquivo
@@ -114,7 +114,7 @@ class RunConfiguration(object):
'fixed_dir': self.fixed_dir,
'dir': self.dir
}
def get_working_directory(self):
return self.dir
@@ -123,13 +123,13 @@ class RunConfiguration(object):
return self.args
else:
return ''
def get_python_arguments(self):
if self.python_args_enabled:
return self.python_args
else:
return ''
def _get_run_configurations():
history_count = CONF.get('run', 'history', 20)
@@ -325,10 +325,10 @@ class RunConfigOptions(QWidget):
class BaseRunConfigDialog(QDialog):
"""Run configuration dialog box, base widget"""
size_change = Signal(QSize)
def __init__(self, parent=None):
QDialog.__init__(self, parent)
# Destroying the C++ object right after closing the dialog box,
# otherwise it may be garbage-collected in another QThread
# (e.g. the editor's analysis thread in Spyder), thus leading to
@@ -338,7 +338,7 @@ class BaseRunConfigDialog(QDialog):
self.setWindowIcon(ima.icon('run_settings'))
layout = QVBoxLayout()
self.setLayout(layout)
def add_widgets(self, *widgets_or_spacings):
"""Add widgets/spacing to dialog vertical layout"""
layout = self.layout()
@@ -347,7 +347,7 @@ class BaseRunConfigDialog(QDialog):
layout.addSpacing(widget_or_spacing)
else:
layout.addWidget(widget_or_spacing)
def add_button_box(self, stdbtns):
"""Create dialog button box and add it to the dialog layout"""
bbox = QDialogButtonBox(stdbtns)
@@ -359,7 +359,7 @@ class BaseRunConfigDialog(QDialog):
btnlayout.addStretch(1)
btnlayout.addWidget(bbox)
self.layout().addLayout(btnlayout)
def resizeEvent(self, event):
"""
Reimplement Qt method to be able to save the widget's size from the
@@ -367,11 +367,11 @@ class BaseRunConfigDialog(QDialog):
"""
QDialog.resizeEvent(self, event)
self.size_change.emit(self.size())
def run_btn_clicked(self):
"""Run button was just clicked"""
pass
def setup(self, fname):
"""Setup Run Configuration dialog with filename *fname*"""
raise NotImplementedError
@@ -383,7 +383,7 @@ class RunConfigOneDialog(BaseRunConfigDialog):
BaseRunConfigDialog.__init__(self, parent)
self.filename = None
self.runconfigoptions = None
def setup(self, fname):
"""Setup Run Configuration dialog with filename *fname*"""
self.filename = fname
@@ -392,7 +392,7 @@ class RunConfigOneDialog(BaseRunConfigDialog):
self.add_widgets(self.runconfigoptions)
self.add_button_box(QDialogButtonBox.Cancel)
self.setWindowTitle(_("Run settings for %s") % osp.basename(fname))
@Slot()
def accept(self):
"""Reimplement Qt method"""
@@ -402,7 +402,7 @@ class RunConfigOneDialog(BaseRunConfigDialog):
configurations.insert(0, (self.filename, self.runconfigoptions.get()))
_set_run_configurations(configurations)
QDialog.accept(self)
def get_configuration(self):
# It is import to avoid accessing Qt C++ object as it has probably
# already been destroyed, due to the Qt.WA_DeleteOnClose attribute
@@ -416,11 +416,11 @@ class RunConfigDialog(BaseRunConfigDialog):
self.file_to_run = None
self.combo = None
self.stack = None
def run_btn_clicked(self):
"""Run button was just clicked"""
self.file_to_run = to_text_string(self.combo.currentText())
def setup(self, fname):
"""Setup Run Configuration dialog with filename *fname*"""
combo_label = QLabel(_("Select a run configuration:"))
@@ -428,7 +428,7 @@ class RunConfigDialog(BaseRunConfigDialog):
self.combo.setMaxVisibleItems(20)
self.combo.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
self.combo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.stack = QStackedWidget()
configurations = _get_run_configurations()
@@ -453,7 +453,7 @@ class RunConfigDialog(BaseRunConfigDialog):
self.add_button_box(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
self.setWindowTitle(_("Run configuration per file"))
def accept(self):
"""Reimplement Qt method"""
configurations = []
@@ -475,7 +475,7 @@ class RunConfigPage(GeneralConfigPage):
NAME = _("Run")
ICON = ima.icon('run')
def setup_page(self):
about_label = QLabel(_("The following are the default options for "
"running files.These options may be overriden "
@@ -500,7 +500,7 @@ class RunConfigPage(GeneralConfigPage):
interpreter_layout.addWidget(self.current_radio)
interpreter_layout.addWidget(self.dedicated_radio)
interpreter_layout.addWidget(self.systerm_radio)
general_group = QGroupBox(_("General settings"))
post_mortem = self.create_checkbox(POST_MORTEM, 'post_mortem', False)
clear_variables = self.create_checkbox(CLEAR_ALL_VARIABLES,
@@ -555,7 +555,7 @@ class RunConfigPage(GeneralConfigPage):
firstrun_cb = self.create_checkbox(
ALWAYS_OPEN_FIRST_RUN % _("Run Settings dialog"),
ALWAYS_OPEN_FIRST_RUN_OPTION, False)
vlayout = QVBoxLayout()
vlayout.addWidget(about_label)
vlayout.addSpacing(10)
+10 -10
Ver Arquivo
@@ -143,40 +143,40 @@ PACKET_NOT_RECEIVED = PacketNotReceived()
if __name__ == '__main__':
if not os.name == 'nt':
# socket read/write testing - client and server in one thread
# (techtonik): the stuff below is placed into public domain
print("-- Testing standard Python socket interface --") # spyder: test-skip
address = ("127.0.0.1", 9999)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind( address )
server.listen(2)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect( address )
client.send("data to be catched".encode('utf-8'))
# accepted server socket is the one we can read from
# note that it is different from server socket
accsock, addr = server.accept()
print('..got "%s" from %s' % (accsock.recv(4096), addr)) # spyder: test-skip
# accsock.close()
# client.send("more data for recv")
#socket.error: [Errno 9] Bad file descriptor
# accsock, addr = server.accept()
#socket.error: [Errno 11] Resource temporarily unavailable
print("-- Testing BSD socket write_packet/read_packet --") # spyder: test-skip
write_packet(client, "a tiny piece of data")
print('..got "%s" from read_packet()' % (read_packet(accsock))) # spyder: test-skip
client.close()
server.close()
print("-- Done.") # spyder: test-skip
+8 -8
Ver Arquivo
@@ -60,7 +60,7 @@ def caller_name(skip=2):
`skip` specifies how many levels of call stack to skip for caller's name.
skip=1 means "who calls me", skip=2 "who calls my caller" etc.
An empty string is returned if skipped levels exceed stack height
"""
stack = inspect.stack()
@@ -68,7 +68,7 @@ def caller_name(skip=2):
if len(stack) < start + 1:
return ''
parentframe = stack[start][0]
name = []
module = inspect.getmodule(parentframe)
# `modname` can be None when frame is executed directly in console
@@ -100,9 +100,9 @@ def log_methods_calls(fname, some_class, prefix=None):
asked - name of `some_class`
called - name of class for which a method is called
defined - name of class where method is defined
Must be used carefully, because it monkeypatches __getattribute__ call.
Example: log_methods_calls('log.log', ShellBaseWidget)
"""
# test if file is writable
@@ -114,7 +114,7 @@ def log_methods_calls(fname, some_class, prefix=None):
if prefix != None:
PREFIX = prefix
MAXWIDTH = {'o_O': 10} # hack with editable closure dict, to align names
def format_prefix(method, methodobj):
"""
--[ ShellBase / Internal / BaseEdit ]------- get_position
@@ -127,7 +127,7 @@ def log_methods_calls(fname, some_class, prefix=None):
line = PREFIX % classnames
MAXWIDTH['o_O'] = max(len(line), MAXWIDTH['o_O'])
return line.ljust(MAXWIDTH['o_O'], '-')
import types
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
@@ -142,6 +142,6 @@ def log_methods_calls(fname, some_class, prefix=None):
result = attr(*args, **kwargs)
return result
return newfunc
some_class.__getattribute__ = __getattribute__
+6 -6
Ver Arquivo
@@ -75,7 +75,7 @@ def to_unicode_from_fs(string):
else:
return unic
return string
def to_fs_from_unicode(unic):
"""
Return a byte string version of unic encoded using the file
@@ -177,7 +177,7 @@ def encode(text, orig_coding):
"""
if orig_coding == 'utf-8-bom':
return BOM_UTF8 + text.encode("utf-8"), 'utf-8-bom'
# Try saving with original encoding
if orig_coding:
try:
@@ -200,16 +200,16 @@ def encode(text, orig_coding):
return text.encode(coding), coding
except (UnicodeError, LookupError):
pass
# Try saving as ASCII
try:
return text.encode('ascii'), 'ascii'
except UnicodeError:
pass
# Save as UTF-8 without BOM
return text.encode('utf-8'), 'utf-8'
def to_unicode(string):
"""Convert a string to unicode"""
if not is_unicode(string):
@@ -223,7 +223,7 @@ def to_unicode(string):
else:
return unic
return string
def write(text, filename, encoding='utf-8', mode='wb'):
"""
+2 -2
Ver Arquivo
@@ -83,7 +83,7 @@ try:
except:
break
return envdict2listdict(reg)
def set_user_env(reg, parent=None):
"""Set HKCU (current user) environment variables"""
reg = listdict2envdict(reg)
@@ -129,7 +129,7 @@ try:
"from a Windows shortcut, otherwise restart any "
"application from which you may have executed it, "
"like <i>Python(x,y) Home</i> for example)"))
def accept(self):
"""Reimplement Qt method"""
set_user_env(listdict2envdict(self.get_value()), parent=self)
+4 -4
Ver Arquivo
@@ -56,14 +56,14 @@ else:
# GetExitCodeProcess uses a special exit code to indicate that the
# process is still running.
STILL_ACTIVE = 259
def _is_pid_running(pid):
"""Taken from https://www.madebuild.org/blog/?p=30"""
kernel32 = ctypes.windll.kernel32
handle = kernel32.OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
if handle == 0:
return False
# If the process exited recently, a pid may still exist for the
# handle. So, check if we can get the exit code.
exit_code = wintypes.DWORD()
@@ -71,7 +71,7 @@ else:
ctypes.byref(exit_code))
is_running = (retval == 0)
kernel32.CloseHandle(handle)
# See if we couldn't get the exit code or the exit code indicates
# that the process is still running.
return is_running or exit_code.value == STILL_ACTIVE
@@ -81,7 +81,7 @@ else:
raise OSError(errno.ESRCH, None)
else:
return
_open = open
# XXX Implement an atomic thingamajig for win32
+2 -2
Ver Arquivo
@@ -47,7 +47,7 @@ def get_submodules(mod):
return []
except:
return [mod]
return submodules
@@ -70,6 +70,6 @@ def get_preferred_submodules():
for m in PREFERRED_MODULES:
submods = get_submodules(m)
submodules += submods
modules_db['submodules'] = submodules
return submodules
+5 -5
Ver Arquivo
@@ -49,7 +49,7 @@ def apply():
'default_config.py')
return open(fname, 'rb').read()
project.Project = PatchedProject
# Patching pycore.PyCore...
from rope.base import pycore
class PatchedPyCore(pycore.PyCore):
@@ -114,7 +114,7 @@ def apply():
return (module, lineno)
return (None, None)
builtins.BuiltinName = PatchedBuiltinName
# [4] Patching several PyDocExtractor methods:
# 1. get_doc:
# To force rope to return the docstring of any object which has one, even
@@ -136,7 +136,7 @@ def apply():
def get_builtin_doc(self, pyobject):
buitin = pyobject.builtin
return getdoc(buitin)
def get_doc(self, pyobject):
if hasattr(pyobject, 'builtin'):
doc = self.get_builtin_doc(pyobject)
@@ -184,7 +184,7 @@ def apply():
if remove_self and self._is_method(pyobject):
return result.replace('(self)', '()').replace('(self, ', '(')
return result
def _get_class_docstring(self, pyclass):
contents = self._trim_docstring(pyclass.get_doc(), indents=0)
supers = [super.get_name() for super in pyclass.get_superclasses()]
@@ -195,7 +195,7 @@ def apply():
if isinstance(init, pyobjects.AbstractFunction):
doc += '\n\n' + self._get_single_function_docstring(init)
return doc
def _get_single_function_docstring(self, pyfunction):
docs = pyfunction.get_doc()
docs = self._trim_docstring(docs, indents=0)
+3 -3
Ver Arquivo
@@ -110,7 +110,7 @@ def alter_subprocess_kwargs_by_platform(**kwargs):
def run_shell_command(cmdstr, **subprocess_kwargs):
"""
Execute the given shell command.
Note that *args and **kwargs will be passed to the subprocess call.
If 'shell' is given in subprocess_kwargs it must be True,
@@ -353,7 +353,7 @@ def check_version(actver, version, cmp_op):
it is assumed that the dependency is satisfied.
Users on dev branches are responsible for keeping their own packages up to
date.
Copyright (C) 2013 The IPython Development Team
Distributed under the terms of the BSD License.
@@ -478,7 +478,7 @@ def is_module_installed(module_name, version=None, installed_version=None,
assert symb in ('>=', '>', '=', '<', '<='),\
"Invalid version condition '%s'" % symb
version = version[match.start():]
return check_version(actver, version, symb)
def is_python_interpreter_valid_name(filename):
+13 -13
Ver Arquivo
@@ -51,7 +51,7 @@ def get_image_label(name, default="not_found.png"):
class MacApplication(QApplication):
"""Subclass to be able to open external files with our Mac app"""
sig_open_external_file = Signal(str)
def __init__(self, *args):
QApplication.__init__(self, *args)
@@ -66,7 +66,7 @@ def qapplication(translate=True, test_time=3):
"""
Return QApplication instance
Creates it if it doesn't already exist
test_time: Time to maintain open the application when testing. It's given
in seconds
"""
@@ -74,7 +74,7 @@ def qapplication(translate=True, test_time=3):
SpyderApplication = MacApplication
else:
SpyderApplication = QApplication
app = SpyderApplication.instance()
if app is None:
# Set Application name for Gnome 3
@@ -168,7 +168,7 @@ def keyevent2tuple(event):
return (event.type(), event.key(), event.modifiers(), event.text(),
event.isAutoRepeat(), event.count())
def tuple2keyevent(past_event):
"""Convert tuple into a QKeyEvent instance"""
return QKeyEvent(*past_event)
@@ -334,11 +334,11 @@ def set_item_user_text(item, text):
def create_bookmark_action(parent, url, title, icon=None, shortcut=None):
"""Create bookmark action"""
@Slot()
def open_url():
return programs.start_file(url)
return create_action( parent, title, shortcut=shortcut, icon=icon,
triggered=open_url)
@@ -361,7 +361,7 @@ def create_module_bookmark_actions(parent, bookmarks):
actions.append(act)
return actions
def create_program_action(parent, text, name, icon=None, nt_name=None):
"""Create action to run a program"""
if is_text_string(icon):
@@ -373,7 +373,7 @@ def create_program_action(parent, text, name, icon=None, nt_name=None):
return create_action(parent, text, icon=icon,
triggered=lambda: programs.run_program(name))
def create_python_script_action(parent, text, icon, package, module, args=[]):
"""Create action to run a GUI based Python script"""
if is_text_string(icon):
@@ -392,7 +392,7 @@ class DialogManager(QObject):
def __init__(self):
QObject.__init__(self)
self.dialogs = {}
def show(self, dialog):
"""Generic method to show a non-modal dialog and keep reference
to the Qt C++ object"""
@@ -409,17 +409,17 @@ class DialogManager(QObject):
lambda eid=id(dialog): self.dialog_finished(eid))
dialog.rejected.connect(
lambda eid=id(dialog): self.dialog_finished(eid))
def dialog_finished(self, dialog_id):
"""Manage non-modal dialog boxes"""
return self.dialogs.pop(dialog_id)
def close_all(self):
"""Close all opened dialog boxes"""
for dlg in list(self.dialogs.values()):
dlg.reject()
def get_filetype_icon(fname):
"""Return file type icon"""
ext = osp.splitext(fname)[1]
@@ -427,7 +427,7 @@ def get_filetype_icon(fname):
ext = ext[1:]
return get_icon( "%s.png" % ext, ima.icon('FileIcon') )
class SpyderAction(QAction):
"""Spyder QAction class wrapper to handle cross platform patches."""
+4 -4
Ver Arquivo
@@ -62,7 +62,7 @@ def fix_indentation(text, indent_chars):
"""Replace tabs by spaces"""
return text.replace('\t', indent_chars)
def is_builtin(text):
"""Test if passed string is the name of a Python builtin object"""
from spyder.py3compat import builtins
@@ -74,7 +74,7 @@ def is_keyword(text):
"""Test if passed string is the name of a Python keyword"""
import keyword
return text in keyword.kwlist
def get_primary_at(source_code, offset, retry=True):
"""Return Python object in *source_code* at *offset*
@@ -137,7 +137,7 @@ def path_components(path):
def differentiate_prefix(path_components0, path_components1):
"""
Return the differentiated prefix of the given two iterables.
Taken from https://stackoverflow.com/q/21498939/438386
"""
longest_prefix = []
@@ -201,7 +201,7 @@ def get_same_name_files(files_path_list, filename):
if filename == os.path.basename(fname):
same_name_files.append(path_components(fname))
return same_name_files
def shortest_path(files_path_list):
"""Shortest path between files in the list."""
if len(files_path_list) > 0:
+1 -1
Ver Arquivo
@@ -269,7 +269,7 @@ def test():
# Full results
for r in a:
print(r) # spyder: test-skip
# Ordered and filtered results
print('\n') # spyder: test-skip
+1 -1
Ver Arquivo
@@ -24,7 +24,7 @@ from spyder.utils.bsdsocket import write_packet, read_packet
def test_bsdsockets():
"""Test write-read packet methods."""
# socket read/write testing - client and server in one thread
# (techtonik): the stuff below is placed into public domain
address = ("127.0.0.1", 9999)
+1 -1
Ver Arquivo
@@ -32,7 +32,7 @@ def environ_dialog(qtbot):
from spyder.utils.environ import EnvDialog
dialog = EnvDialog()
qtbot.addWidget(dialog)
return dialog
+1 -1
Ver Arquivo
@@ -24,7 +24,7 @@ def test_system():
assert windows_memory_usage() > 0
else:
assert memory_usage() > 0
if __name__ == "__main__":
+1 -1
Ver Arquivo
@@ -119,7 +119,7 @@ def get_hg_revision(repopath):
def get_git_revision(repopath):
"""
Return Git revision for the repository located at repopath
Result is a tuple (latest commit hash, branch), with None values on
error
"""
+2 -2
Ver Arquivo
@@ -80,7 +80,7 @@ class PythonWorker(QObject):
self.sig_finished.emit(self, output, error)
self._is_finished = True
class ProcessWorker(QObject):
"""Process worker based on a QProcess for non blocking UI."""
@@ -324,7 +324,7 @@ def ready_print(worker, output, error): # pragma: no cover
"""Print worker output for tests."""
print(worker, output, error) # spyder: test-skip
def sleeping_func(arg, secs=10, result_queue=None):
"""This methods illustrates how the workers can be used."""
import time
+23 -23
Ver Arquivo
@@ -131,7 +131,7 @@ class WebView(QWebEngineView):
size = font.pixelSize()
settings.setFontSize(settings.DefaultFontSize, size)
settings.setFontSize(settings.DefaultFixedFontSize, size)
def apply_zoom_factor(self):
"""Apply zoom factor"""
if hasattr(self, 'setZoomFactor'):
@@ -140,12 +140,12 @@ class WebView(QWebEngineView):
else:
# Qt v4.4
self.setTextSizeMultiplier(self.zoom_factor)
def set_zoom_factor(self, zoom_factor):
"""Set zoom factor"""
self.zoom_factor = zoom_factor
self.apply_zoom_factor()
def get_zoom_factor(self):
"""Return zoom factor"""
return self.zoom_factor
@@ -161,12 +161,12 @@ class WebView(QWebEngineView):
"""Zoom in"""
self.zoom_factor += .1
self.apply_zoom_factor()
#------ QWebEngineView API -------------------------------------------------------
def createWindow(self, webwindowtype):
import webbrowser
webbrowser.open(to_text_string(self.url().toString()))
def contextMenuEvent(self, event):
menu = QMenu(self)
actions = [self.pageAction(QWebEnginePage.Back),
@@ -204,32 +204,32 @@ class WebBrowser(QWidget):
"""
def __init__(self, parent=None, options_button=None):
QWidget.__init__(self, parent)
self.home_url = None
self.webview = WebView(self)
self.webview.loadFinished.connect(self.load_finished)
self.webview.titleChanged.connect(self.setWindowTitle)
self.webview.urlChanged.connect(self.url_changed)
home_button = create_toolbutton(self, icon=ima.icon('home'),
tip=_("Home"),
triggered=self.go_home)
zoom_out_button = action2button(self.webview.zoom_out_action)
zoom_in_button = action2button(self.webview.zoom_in_action)
pageact2btn = lambda prop: action2button(self.webview.pageAction(prop),
parent=self.webview)
refresh_button = pageact2btn(QWebEnginePage.Reload)
stop_button = pageact2btn(QWebEnginePage.Stop)
previous_button = pageact2btn(QWebEnginePage.Back)
next_button = pageact2btn(QWebEnginePage.Forward)
stop_button.setEnabled(False)
self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))
self.webview.loadFinished.connect(lambda: stop_button.setEnabled(False))
progressbar = QProgressBar(self)
progressbar.setTextVisible(False)
progressbar.hide()
@@ -258,7 +258,7 @@ class WebBrowser(QWidget):
label, self.url_combo, zoom_out_button, zoom_in_button,
refresh_button, progressbar, stop_button):
hlayout.addWidget(widget)
if options_button:
hlayout.addWidget(options_button)
@@ -266,20 +266,20 @@ class WebBrowser(QWidget):
layout.addWidget(self.webview)
layout.addWidget(self.find_widget)
self.setLayout(layout)
def get_label(self):
"""Return address label text"""
return _("Address:")
def set_home_url(self, text):
"""Set home URL"""
self.home_url = QUrl(text)
def set_url(self, url):
"""Set current URL"""
self.url_changed(url)
self.go_to(url)
def go_to(self, url_or_text):
"""Go to page *address*"""
if is_text_string(url_or_text):
@@ -293,28 +293,28 @@ class WebBrowser(QWidget):
"""Go to home page"""
if self.home_url is not None:
self.set_url(self.home_url)
def text_to_url(self, text):
"""Convert text address into QUrl object"""
return QUrl(text)
def url_combo_activated(self, valid):
"""Load URL from combo box first item"""
text = to_text_string(self.url_combo.currentText())
self.go_to(self.text_to_url(text))
def load_finished(self, ok):
if not ok:
self.webview.setHtml(_("Unable to load page"))
def url_to_text(self, url):
"""Convert QUrl object to displayed text in combo box"""
return url.toString()
def url_changed(self, url):
"""Displayed URL has changed -> updating URL combo box"""
self.url_combo.add_text(self.url_to_text(url))
def icon_changed(self):
self.url_combo.setItemIcon(self.url_combo.currentIndex(),
self.webview.icon())
+6 -6
Ver Arquivo
@@ -18,24 +18,24 @@ class ColorButton(QPushButton):
Color choosing push button
"""
colorChanged = Signal(QColor)
def __init__(self, parent=None):
QPushButton.__init__(self, parent)
self.setFixedSize(20, 20)
self.setIconSize(QSize(12, 12))
self.clicked.connect(self.choose_color)
self._color = QColor()
def choose_color(self):
color = QColorDialog.getColor(self._color, self.parentWidget(),
'Select Color',
QColorDialog.ShowAlphaChannel)
if color.isValid():
self.set_color(color)
def get_color(self):
return self._color
@Slot(QColor)
def set_color(self, color):
if color != self._color:
@@ -44,7 +44,7 @@ class ColorButton(QPushButton):
pixmap = QPixmap(self.iconSize())
pixmap.fill(color)
self.setIcon(QIcon(pixmap))
color = Property("QColor", get_color, set_color)
@@ -88,6 +88,6 @@ class ColorLayout(QHBoxLayout):
def update_text(self, color):
self.lineedit.setText(color.name())
def text(self):
return self.lineedit.text()
+2 -2
Ver Arquivo
@@ -107,7 +107,7 @@ class DependenciesDialog(QDialog):
def test():
"""Run dependency widget test"""
from spyder import dependencies
# Test sample
dependencies.add("IPython", "Enhanced Python interpreter", ">=20.0")
dependencies.add("matplotlib", "Interactive data plotting", ">=1.0")
@@ -115,7 +115,7 @@ def test():
dependencies.add("foo", "Non-existent module", ">=1.0")
dependencies.add("numpy", "Edit arrays in Variable Explorer", ">=0.10",
optional=True)
from spyder.utils.qthelpers import qapplication
app = qapplication()
dlg = DependenciesDialog(None)
+22 -22
Ver Arquivo
@@ -34,7 +34,7 @@ from spyder.widgets.comboboxes import PatternComboBox
def is_position_sup(pos1, pos2):
"""Return True is pos1 > pos2"""
return pos1 > pos2
def is_position_inf(pos1, pos2):
"""Return True is pos1 < pos2"""
return pos1 < pos2
@@ -61,15 +61,15 @@ class FindReplace(QWidget):
self.enable_replace = enable_replace
self.editor = None
self.is_code_editor = None
glayout = QGridLayout()
glayout.setContentsMargins(0, 0, 0, 0)
self.setLayout(glayout)
self.close_button = create_toolbutton(self, triggered=self.hide,
icon=ima.icon('DialogCloseButton'))
glayout.addWidget(self.close_button, 0, 0)
# Find layout
self.search_text = PatternComboBox(self, tip=_("Search string"),
adjust_to_minimum=False)
@@ -101,20 +101,20 @@ class FindReplace(QWidget):
tip=_("Regular expression"))
self.re_button.setCheckable(True)
self.re_button.toggled.connect(lambda state: self.find())
self.case_button = create_toolbutton(self,
icon=ima.icon(
"format_letter_case"),
tip=_("Case Sensitive"))
self.case_button.setCheckable(True)
self.case_button.toggled.connect(lambda state: self.find())
self.words_button = create_toolbutton(self,
icon=get_icon("whole_words.png"),
tip=_("Whole words"))
self.words_button.setCheckable(True)
self.words_button.toggled.connect(lambda state: self.find())
self.highlight_button = create_toolbutton(self,
icon=get_icon("highlight.png"),
tip=_("Highlight matches"))
@@ -156,7 +156,7 @@ class FindReplace(QWidget):
text_beside_icon=True)
self.replace_all_button.clicked.connect(self.update_replace_combo)
self.replace_all_button.clicked.connect(self.update_search_combo)
self.replace_layout = QHBoxLayout()
widgets = [replace_with, self.replace_text, self.replace_button,
self.replace_sel_button, self.replace_all_button]
@@ -166,13 +166,13 @@ class FindReplace(QWidget):
self.widgets.extend(widgets)
self.replace_widgets = widgets
self.hide_replace()
self.search_text.setTabOrder(self.search_text, self.replace_text)
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.shortcuts = self.create_shortcuts(parent)
self.highlight_timer = QTimer(self)
self.highlight_timer.setSingleShot(True)
self.highlight_timer.setInterval(1000)
@@ -229,13 +229,13 @@ class FindReplace(QWidget):
default (string): default key sequence
"""
return [sc.data for sc in self.shortcuts]
def update_search_combo(self):
self.search_text.lineEdit().returnPressed.emit()
def update_replace_combo(self):
self.replace_text.lineEdit().returnPressed.emit()
def toggle_replace_widgets(self):
if self.enable_replace:
# Toggle replace widgets
@@ -255,7 +255,7 @@ class FindReplace(QWidget):
self.highlight_matches()
else:
self.clear_matches()
def show(self, hide_replace=True):
"""Overrides Qt Method"""
QWidget.show(self)
@@ -281,7 +281,7 @@ class FindReplace(QWidget):
except AttributeError:
# We can't do this for all widgets, e.g. WebView's
pass
# Now that text value is sorted out, use it for the search
if text and not self.search_text.currentText() or highlighted:
self.search_text.setEditText(text)
@@ -301,18 +301,18 @@ class FindReplace(QWidget):
if self.editor is not None:
self.editor.setFocus()
self.clear_matches()
def show_replace(self):
"""Show replace widgets"""
self.show(hide_replace=False)
for widget in self.replace_widgets:
widget.show()
def hide_replace(self):
"""Hide replace widgets"""
for widget in self.replace_widgets:
widget.hide()
def refresh(self):
"""Refresh widget"""
if self.isHidden():
@@ -324,7 +324,7 @@ class FindReplace(QWidget):
widget.setEnabled(state)
if state:
self.find()
def set_editor(self, editor, refresh=True):
"""
Set associated editor/web page:
@@ -537,7 +537,7 @@ class FindReplace(QWidget):
"""Replace and find all matching occurrences"""
self.replace_find(focus_replace_text, replace_all=True)
@Slot()
def replace_find_selection(self, focus_replace_text=False):
"""Replace and find in the current selection"""
+21 -21
Ver Arquivo
@@ -30,22 +30,22 @@ class OneColumnTree(QTreeWidget):
self.expand_all_action = None
self.expand_selection_action = None
self.common_actions = self.setup_common_actions()
self.__expanded_state = None
self.itemSelectionChanged.connect(self.item_selection_changed)
self.item_selection_changed()
def activated(self, item):
"""Double-click event"""
raise NotImplementedError
def clicked(self, item):
pass
def set_title(self, title):
self.setHeaderLabels([title])
def setup_common_actions(self):
"""Setup context menu common actions"""
self.collapse_all_action = create_action(self,
@@ -72,7 +72,7 @@ class OneColumnTree(QTreeWidget):
return [self.collapse_all_action, self.expand_all_action,
self.restore_action, None,
self.collapse_selection_action, self.expand_selection_action]
def get_menu_actions(self):
"""Returns a list of menu actions"""
items = self.selectedItems()
@@ -97,19 +97,19 @@ class OneColumnTree(QTreeWidget):
self.collapseAll()
for item in self.get_top_level_items():
self.expandItem(item)
def is_item_expandable(self, item):
"""To be reimplemented in child class
See example in project explorer widget"""
return True
def __expand_item(self, item):
if self.is_item_expandable(item):
self.expandItem(item)
for index in range(item.childCount()):
child = item.child(index)
self.__expand_item(child)
@Slot()
def expand_selection(self):
items = self.selectedItems()
@@ -119,7 +119,7 @@ class OneColumnTree(QTreeWidget):
self.__expand_item(item)
if items:
self.scrollToItem(items[0])
def __collapse_item(self, item):
self.collapseItem(item)
for index in range(item.childCount()):
@@ -135,17 +135,17 @@ class OneColumnTree(QTreeWidget):
self.__collapse_item(item)
if items:
self.scrollToItem(items[0])
def item_selection_changed(self):
"""Item selection has changed"""
is_selection = len(self.selectedItems()) > 0
self.expand_selection_action.setEnabled(is_selection)
self.collapse_selection_action.setEnabled(is_selection)
def get_top_level_items(self):
"""Iterate over top level items"""
return [self.topLevelItem(_i) for _i in range(self.topLevelItemCount())]
def get_items(self):
"""Return items (excluding top level items)"""
itemlist = []
@@ -157,24 +157,24 @@ class OneColumnTree(QTreeWidget):
for tlitem in self.get_top_level_items():
add_to_itemlist(tlitem)
return itemlist
def get_scrollbar_position(self):
return (self.horizontalScrollBar().value(),
self.verticalScrollBar().value())
def set_scrollbar_position(self, position):
hor, ver = position
self.horizontalScrollBar().setValue(hor)
self.verticalScrollBar().setValue(ver)
def get_expanded_state(self):
self.save_expanded_state()
return self.__expanded_state
def set_expanded_state(self, state):
self.__expanded_state = state
self.restore_expanded_state()
def save_expanded_state(self):
"""Save all items expanded state"""
self.__expanded_state = {}
@@ -190,7 +190,7 @@ class OneColumnTree(QTreeWidget):
browse_children(citem)
for tlitem in self.get_top_level_items():
browse_children(tlitem)
def restore_expanded_state(self):
"""Restore all items expanded state"""
if self.__expanded_state is None:
@@ -209,9 +209,9 @@ class OneColumnTree(QTreeWidget):
for index, item in enumerate(items):
self.insertTopLevelItem(index, item)
self.restore_expanded_state()
def contextMenuEvent(self, event):
"""Override Qt method"""
self.update_menu()
self.menu.popup(event.globalPos())
+15 -15
Ver Arquivo
@@ -29,17 +29,17 @@ from spyder.py3compat import PY2
class PathManager(QDialog):
redirect_stdio = Signal(bool)
def __init__(self, parent=None, pathlist=None, ro_pathlist=None,
not_active_pathlist=None, sync=True):
QDialog.__init__(self, parent)
# Destroying the C++ object right after closing the dialog box,
# otherwise it may be garbage-collected in another QThread
# (e.g. the editor's analysis thread in Spyder), thus leading to
# a segmentation fault on UNIX or an application crash on Windows
self.setAttribute(Qt.WA_DeleteOnClose)
assert isinstance(pathlist, list)
self.pathlist = pathlist
if not_active_pathlist is None:
@@ -48,18 +48,18 @@ class PathManager(QDialog):
if ro_pathlist is None:
ro_pathlist = []
self.ro_pathlist = ro_pathlist
self.last_path = getcwd_or_home()
self.setWindowTitle(_("PYTHONPATH manager"))
self.setWindowIcon(ima.icon('pythonpath'))
self.resize(500, 300)
self.selection_widgets = []
layout = QVBoxLayout()
self.setLayout(layout)
top_layout = QHBoxLayout()
layout.addLayout(top_layout)
self.toolbar_widgets1 = self.setup_top_toolbar(top_layout)
@@ -73,12 +73,12 @@ class PathManager(QDialog):
layout.addLayout(bottom_layout)
self.sync_button = None
self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout, sync)
# Buttons configuration
bbox = QDialogButtonBox(QDialogButtonBox.Close)
bbox.rejected.connect(self.reject)
bottom_layout.addWidget(bbox)
self.update_list()
self.refresh()
@@ -91,7 +91,7 @@ class PathManager(QDialog):
layout.setAlignment(Qt.AlignLeft)
for widget in widgets:
layout.addWidget(widget)
def setup_top_toolbar(self, layout):
toolbar = []
movetop_button = create_toolbutton(self,
@@ -121,7 +121,7 @@ class PathManager(QDialog):
self.selection_widgets.extend(toolbar)
self._add_widgets_to_layout(layout, toolbar)
return toolbar
def setup_bottom_toolbar(self, layout, sync=True):
toolbar = []
add_button = create_toolbutton(self, text=_('Add path'),
@@ -200,7 +200,7 @@ class PathManager(QDialog):
def remove_from_not_active_pathlist(self, path):
if path in self.not_active_pathlist:
self.not_active_pathlist.remove(path)
def update_list(self):
"""Update path list"""
self.listwidget.clear()
@@ -218,7 +218,7 @@ class PathManager(QDialog):
item.setCheckState(Qt.Checked)
self.listwidget.addItem(item)
self.refresh()
def refresh(self, row=None):
"""Refresh widget"""
for widget in self.selection_widgets:
@@ -226,7 +226,7 @@ class PathManager(QDialog):
not_empty = self.listwidget.count() > 0
if self.sync_button is not None:
self.sync_button.setEnabled(not_empty)
def move_to(self, absolute=None, relative=None):
index = self.listwidget.currentRow()
if absolute is not None:
+2 -2
Ver Arquivo
@@ -113,7 +113,7 @@ class BaseTimerStatus(StatusBarWidget):
self._interval = interval
if self.timer is not None:
self.timer.setInterval(interval)
def import_test(self):
"""Raise ImportError if feature is not supported."""
raise NotImplementedError
@@ -129,7 +129,7 @@ class BaseTimerStatus(StatusBarWidget):
def get_value(self):
"""Return formatted text value."""
raise NotImplementedError
def update_status(self):
"""Update status label widget, if widget is visible."""
if self.isVisible():
+21 -21
Ver Arquivo
@@ -136,7 +136,7 @@ class TabBar(QTabBar):
"""Tabs base class with drag and drop support"""
sig_move_tab = Signal((int, int), (str, int, int))
sig_change_name = Signal(str)
def __init__(self, parent, ancestor, rename_tabs=False, split_char='',
split_index=0):
QTabBar.__init__(self, parent)
@@ -145,7 +145,7 @@ class TabBar(QTabBar):
# To style tabs on Mac
if sys.platform == 'darwin':
self.setObjectName('plugin-tab')
# Dragging tabs
self.__drag_start_pos = QPoint()
self.setAcceptDrops(True)
@@ -166,7 +166,7 @@ class TabBar(QTabBar):
if event.button() == Qt.LeftButton:
self.__drag_start_pos = QPoint(event.pos())
QTabBar.mousePressEvent(self, event)
def mouseMoveEvent(self, event):
"""Override Qt method"""
# FIXME: This was added by Pierre presumably to move tabs
@@ -193,7 +193,7 @@ class TabBar(QTabBar):
# drag.setMimeData(mimeData)
# drag.exec_()
QTabBar.mouseMoveEvent(self, event)
def dragEnterEvent(self, event):
"""Override Qt method"""
mimeData = event.mimeData()
@@ -204,7 +204,7 @@ class TabBar(QTabBar):
event.acceptProposedAction()
QTabBar.dragEnterEvent(self, event)
def dropEvent(self, event):
"""Override Qt method"""
mimeData = event.mimeData()
@@ -214,7 +214,7 @@ class TabBar(QTabBar):
index_to = self.count()
if int(mimeData.data("tabbar-id")) != id(self):
tabwidget_from = to_text_string(mimeData.data("tabwidget-id"))
# We pass self object ID as a QString, because otherwise it would
# depend on the platform: long for 64bit, int for 32bit. Replacing
# by long all the time is not working on some 32bit platforms
@@ -240,11 +240,11 @@ class TabBar(QTabBar):
# Event is not interesting, raise to parent
QTabBar.mouseDoubleClickEvent(self, event)
class BaseTabs(QTabWidget):
"""TabWidget with context menu and corner widgets"""
sig_close_tab = Signal(int)
def __init__(self, parent, actions=None, menu=None,
corner_widgets=None, menu_use_tooltips=False):
QTabWidget.__init__(self, parent)
@@ -256,14 +256,14 @@ class BaseTabs(QTabWidget):
self.corner_widgets = {}
self.menu_use_tooltips = menu_use_tooltips
if menu is None:
self.menu = QMenu(self)
if actions:
add_actions(self.menu, actions)
else:
self.menu = menu
# Corner widgets
if corner_widgets is None:
corner_widgets = {}
@@ -300,7 +300,7 @@ class BaseTabs(QTabWidget):
# Testing if tab names are filenames
dirnames.append(osp.dirname(text))
offset = None
# If tab names are all filenames, removing common path:
if len(names) == len(dirnames):
common = get_common_path(dirnames)
@@ -348,17 +348,17 @@ class BaseTabs(QTabWidget):
clayout.addWidget(widget)
cwidget.setLayout(clayout)
cwidget.show()
def add_corner_widgets(self, widgets, corner=Qt.TopRightCorner):
self.set_corner_widgets({corner:
self.corner_widgets.get(corner, [])+widgets})
def contextMenuEvent(self, event):
"""Override Qt method"""
self.setCurrentIndex(self.tabBar().tabAt(event.pos()))
if self.menu:
self.menu.popup(event.globalPos())
def mousePressEvent(self, event):
"""Override Qt method"""
if event.button() == Qt.MidButton:
@@ -368,7 +368,7 @@ class BaseTabs(QTabWidget):
event.accept()
return
QTabWidget.mousePressEvent(self, event)
def keyPressEvent(self, event):
"""Override Qt method"""
ctrl = event.modifiers() & Qt.ControlModifier
@@ -400,7 +400,7 @@ class BaseTabs(QTabWidget):
else:
index = self.currentIndex()+delta
self.setCurrentIndex(index)
def set_close_function(self, func):
"""Setting Tabs close function
None -> tabs are not closable"""
@@ -418,14 +418,14 @@ class BaseTabs(QTabWidget):
tip=_("Close current tab"))
self.setCornerWidget(close_button if state else None)
class Tabs(BaseTabs):
"""BaseTabs widget with movable tabs and tab navigation shortcuts"""
# Signals
move_data = Signal(int, int)
move_tab_finished = Signal()
sig_move_tab = Signal(str, str, int, int)
def __init__(self, parent, actions=None, menu=None,
corner_widgets=None, menu_use_tooltips=False,
rename_tabs=False, split_char='',
@@ -458,11 +458,11 @@ class Tabs(BaseTabs):
tip, text = self.tabToolTip(index_from), self.tabText(index_from)
icon, widget = self.tabIcon(index_from), self.widget(index_from)
current_widget = self.currentWidget()
self.removeTab(index_from)
self.insertTab(index_to, widget, icon, text)
self.setTabToolTip(index_to, tip)
self.setCurrentWidget(current_widget)
self.move_tab_finished.emit()
@@ -470,7 +470,7 @@ class Tabs(BaseTabs):
def move_tab_from_another_tabwidget(self, tabwidget_from,
index_from, index_to):
"""Move tab from a tabwidget to another"""
# We pass self object IDs as QString objs, because otherwise it would
# depend on the platform: long for 64bit, int for 32bit. Replacing
# by long all the time is not working on some 32bit platforms
+3 -3
Ver Arquivo
@@ -45,10 +45,10 @@ def get_stdlib_modules():
"""
Returns a list containing the names of all the modules available in the
standard library.
Based on the function get_root_modules from the IPython project.
Present in IPython.core.completerlib in v0.13.1
Copyright (C) 2010-2011 The IPython Development Team.
Distributed under the terms of the BSD License.
"""
@@ -56,7 +56,7 @@ def get_stdlib_modules():
for path in sys.path[1:]:
if 'site-packages' not in path:
modules += module_list(path)
modules = set(modules)
if '__init__' in modules:
modules.remove('__init__')