From 24a9171d90dee67ab8e2bc1f136feb1413391e47 Mon Sep 17 00:00:00 2001 From: Catherine Devlin Date: Tue, 6 Jan 2015 20:31:52 -0500 Subject: [PATCH] In table cells, make leading spaces nonbreaking --- ipython-sql.wpr | 2 +- ipython-sql.wpu | 358 +++++++++++++++++++++++++----------------------- src/sql/run.py | 70 ++++++---- 3 files changed, 230 insertions(+), 200 deletions(-) diff --git a/ipython-sql.wpr b/ipython-sql.wpr index 6b928e4..879c492 100644 --- a/ipython-sql.wpr +++ b/ipython-sql.wpr @@ -1,5 +1,5 @@ #!wing -#!version=4.0 +#!version=5.0 ################################################################## # Wing IDE project file # ################################################################## diff --git a/ipython-sql.wpu b/ipython-sql.wpu index 82a95e4..8d63c95 100644 --- a/ipython-sql.wpu +++ b/ipython-sql.wpu @@ -1,5 +1,5 @@ #!wing -#!version=4.0 +#!version=5.0 ################################################################## # Wing IDE project file : User-specific branch # ################################################################## @@ -8,7 +8,7 @@ debug.err-values = {None: {}} guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'windows': [{'name': 'pl1wewRCfZASfmghIM3JwuU1ss'\ 'ZVfe0h', - 'size-state': '', + 'size-state': 'maximized', 'type': 'dock', 'view': {'area': 'tall', 'constraint': None, @@ -18,25 +18,17 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'notebook_display': 'normal', 'notebook_percent': 0.24701670644391405, 'override_title': None, - 'pagelist': [('debug-stack', - 'tall', - 1, - {'codeline-mode': 'below'}), - ('indent', - 'tall', - 2, - {}), - ('project', + 'pagelist': [('project', 'tall', 0, {'tree-state': {'file-sort-method': 'by name', 'list-files-first': False, - 'tree-states': {'deep': {'column-widths': [1.0], - 'expanded-nodes': [(2,), - (3,), - (3, - 1)], - 'selected-nodes': [(3, + 'tree-states': {'deep': {'expanded-nodes': [(1,), + (1, + 1), + (2,), + (3,)], + 'selected-nodes': [(1, 1, 3)], 'top-node': (0,)}}, @@ -49,19 +41,26 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', u'django': [], u'html': [], u'py': []}}), - ('source-assistant', - 'tall', - 2, - {'docstring-during-complete': False, - 'wrap-lines': True}), ('browser', 'tall', 0, - {'all_tree_states': {u'By Module': {'column-w'\ - 'idths': [1.0], + {'all_tree_states': {loc('../cmd2/NEWS.txt'): {''\ + 'column-widths': [1.0], 'expanded-nodes': [], - 'selected-nodes': [None], + 'selected-nodes': [], 'top-node': None}, + loc('../cpython/Lib/doctest.py'): {'column-widths': [1.0], + 'expanded-nodes': [], + 'selected-nodes': [[('generic attribute', + loc('../cpython/Lib/doctest.py'), + 'TestResults')]], + 'top-node': [('generic attribute', + loc('../cpython/Lib/doctest.py'), + 'BLANKLINE_MARKER')]}, + u'By Module': {'column-widths': [1.0], + 'expanded-nodes': [], + 'selected-nodes': [None], + 'top-node': None}, loc('../../Dropbox/pillars2/pillars_gdsii_2.py'): {'column-widths': [1.0], 'expanded-nodes': [], 'selected-nodes': [], @@ -141,10 +140,6 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'top-node': [('function def', loc('../../org/mpwfw/ipy/tst.py'), 'f')]}, - loc('../cmd2/NEWS.txt'): {'column-widths': [1.0], - 'expanded-nodes': [], - 'selected-nodes': [], - 'top-node': None}, loc('../cmd2/cmd2.py'): {'column-widths': [1.0], 'expanded-nodes': [], 'selected-nodes': [], @@ -161,14 +156,6 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'top-node': [('generic attribute', loc('../cmd2/setup.py'), 'install_requires')]}, - loc('../cpython/Lib/doctest.py'): {'column-widths': [1.0], - 'expanded-nodes': [], - 'selected-nodes': [[('generic attribute', - loc('../cpython/Lib/doctest.py'), - 'TestResults')]], - 'top-node': [('generic attribute', - loc('../cpython/Lib/doctest.py'), - 'BLANKLINE_MARKER')]}, loc('../ipython_doctester/doctester.py'): {'column-widths': [1.0], 'expanded-nodes': [], 'selected-nodes': [], @@ -240,12 +227,24 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', ('uses', 'tall', 0, + {}), + ('debug-stack', + 'tall', + 1, + {'codeline-mode': 'below'}), + ('indent', + 'tall', + 2, + {}), + ('source-assistant', + 'tall', + 2, {})], 'primary_view_state': {'area': 'wide', 'constraint': None, 'current_pages': [11], 'notebook_display': 'normal', - 'notebook_percent': 0.30332409972299168, + 'notebook_percent': 0.3033240997229917, 'override_title': None, 'pagelist': [('bookmarks', 'wide', @@ -268,56 +267,44 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', ('debug-probe', 'wide', 2, - {'attrib-starts': [], + {'active-range': (None, + -1, + -1), + 'attrib-starts': [], 'first-line': 0, 'folded-linenos': [], - 'history': {None: ['uld'], - u'file:/home/catherine/Dropbox/pillars2/pillars_gdsii_2.py': [''\ - 'self.matrix\n', - 'dir(self_matrix)\n', - 'dir(self.matrix)\n', - '( (self.n0 * (2 - (self.rho/self.matrix.big_r_um) ** 2)**0.5\n '\ - ' - air_index) * self.matrix.lattice_constant_um ** 2'\ - ')\n\n', - '(self.rho/self.matrix.big_r_um) ** 2\n', - '(2 - (self.rho/self.matrix.big_r_um) ** 2)**0.5\n', - 'self.rho\n', - 'self.xindex\n', - 'self.yindex\n', - 'self.matrix.big_r_um\n', - 'self.matrix.x_max_um\n'], - u'file:/home/catherine/itninja/database/improve/nltk_data/process.py': [''\ - 'result\n'], - u'file:/home/catherine/itninja/database/improve/pos_corpus_auto.py': [''\ - 'print line\n', - 'word\n', - 'replacement\n', - 'line\n'], - u'file:/home/catherine/org/mpwfw/ipy/tst.py': [''\ - 'bool(tests)\n', - 'len(tests)\n', - 'tests[0]\n', - 'test\n', - 'dir(test)\n', - 'test.examples\n', - 'func\n', - 'func.__name__\n', - 'self.lines.splitlines()\n', - 'self.lines\n', - 'dir(self.lines)\n', - 'raw_txt\n', - 'print raw_txt\n', - 'self.called\n'], - u'file:/home/catherine/proj/ipython_doctester/doctester.py': [''\ - 'txt\n', - 'print txt\n', - 'str(captured)\n', - 'print captured\n', - 'captured\n'], - u'file:/home/catherine/proj/ipython_doctester/tst.py': [''\ - 'test.globs\n', - 't.globs\n', - 't\n']}, + 'history': {u'file:/home/catherine/ve/fec2/bin/rdbms-subsetter': [''\ + 'target.exists\n', + 'target.exists(**dict(source_row))\n', + 'target.db\n', + 'child_tbl\n', + 'target_parent_row\n', + 'source_parent_row\n', + 'self\n', + 'self.inspector.\n', + 'self.inspector.get_primary_keys(target.name)\n', + 'args.keys()\n', + "args.force_rows = {'dimcand': [10071936,]}\n", + 'args\n', + 'args.require_children\n', + 'args.for\n', + 'args.force\n', + 'args.fraction\n', + 'source_by_pk\n', + 'args.force_rows\n', + 'args.force_rows[source_name]\n', + 'self.db.inspector.get_primary_keys(self.name)\n', + 'pk_name\n', + 'pk\n', + '**{pk_name:pk}\n', + 'print **{pk_name:pk}\n', + 'print **({pk_name:pk})\n', + 'print {pk_name: pk}\n', + 'print slct\n', + 'source_row\n', + 'target\n', + 'source_by_pk(-1)\n']}, + 'launch-id': None, 'sel-line': 0, 'sel-line-start': 0, 'selection_end': 0, @@ -341,16 +328,20 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', ('os-command', 'wide', 1, - {'last-percent': 0.80000000000000004, + {'last-percent': 0.8, 'toolbox-percent': 1.0, 'toolbox-tree-sel': ''}), ('python-shell', 'wide', 2, - {'attrib-starts': [], + {'active-range': (None, + -1, + -1), + 'attrib-starts': [], 'first-line': 0, 'folded-linenos': [], 'history': {}, + 'launch-id': None, 'sel-line': 3, 'sel-line-start': 130, 'selection_end': 130, @@ -368,7 +359,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'fMatchCase': False, 'fOmitBinary': True, 'fRegexFlags': 46, - 'fReplaceText': '', + 'fReplaceText': u'', 'fReverse': False, 'fSearchText': u'.new', 'fStartPos': 0, @@ -401,7 +392,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'fRegexFlags': 46, 'fReplaceText': u'called', 'fReverse': False, - 'fSearchText': u'sys', + 'fSearchText': u'//', 'fStartPos': 0, 'fStyle': 'regex', 'fWholeWords': False, @@ -433,28 +424,19 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 1, {'node-states': [], 'tree-state': {'column-widths': [0.38426349496797807, - 0.61573650503202193], + 0.6157365050320219], 'expanded-nodes': [], 'selected-nodes': [], 'top-node': (0,)}})], - 'primary_view_state': {'editor_states': {'bookmarks': ([[loc('../../org/mpwfw/disk/ColorWall/run.py'), + 'primary_view_state': {'editor_states': ({'bookmarks': ([(loc('../ipython_doctester/ipython_doctester.py'), {'attrib-starts': [], - 'first-line': 30, + 'first-line': 19, 'folded-linenos': [], - 'sel-line': 42, - 'sel-line-start': 1437, - 'selection_end': 1437, - 'selection_start': 1437}, - 1357513098.9413929], - (loc('../ipython_doctester/ipython_doctester.py'), - {'attrib-starts': [], - 'first-line': 19, - 'folded-linenos': [], - 'sel-line': 26, - 'sel-line-start': 696, - 'selection_end': 724, - 'selection_start': 724}, - 1358988102.8065691), + 'sel-line': 26, + 'sel-line-start': 696, + 'selection_end': 724, + 'selection_start': 724}, + 1358988102.806569), [loc('../ipython_doctester/ipython_doctester.py'), {'attrib-starts': [], 'first-line': 19, @@ -463,7 +445,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 696, 'selection_end': 724, 'selection_start': 724}, - 1358988140.2782991], + 1358988140.278299], [loc('../../Dropbox/wof/trough_trial_1.py'), {'attrib-starts': [], 'first-line': 0, @@ -490,7 +472,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 1397, 'selection_end': 1418, 'selection_start': 1418}, - 1363624868.1423759), + 1363624868.142376), (loc('../cmd2/NEWS.txt'), {'attrib-starts': [], 'first-line': 0, @@ -499,7 +481,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 206, 'selection_end': 313, 'selection_start': 313}, - 1363624892.6995621), + 1363624892.699562), [loc('../cmd2/patch.diff'), {'attrib-starts': [], 'first-line': 0, @@ -517,7 +499,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 361, 'selection_end': 422, 'selection_start': 422}, - 1363626438.5112541), + 1363626438.511254), (loc('../cmd2/cmd2.py'), {'attrib-starts': [], 'first-line': 38, @@ -535,7 +517,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 350, 'selection_end': 370, 'selection_start': 370}, - 1363626634.4066069), + 1363626634.406607), (loc('../cmd2/NEWS.txt'), {'attrib-starts': [], 'first-line': 6, @@ -601,7 +583,7 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 1116, 'selection_end': 1122, 'selection_start': 1122}, - 1364592268.7543321), + 1364592268.754332), [loc('../../itninja/database/improve/condense.py'), {'attrib-starts': [], 'first-line': 15, @@ -610,65 +592,95 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'sel-line-start': 1116, 'selection_end': 1122, 'selection_start': 1122}, - 1364592275.5137169], + 1364592275.513717], [loc('src/sql/run.py'), - {'attrib-starts': [('run', - 25)], - 'first-line': 13, + {'attrib-starts': [('ResultSet', + 68), + ('ResultSet.__init__', + 74)], + 'first-line': 68, 'folded-linenos': [], - 'sel-line': 29, - 'sel-line-start': 1006, - 'selection_end': 1050, - 'selection_start': 1050}, - 1364621577.7297421]], - 19), - 'current-loc': loc('src/sql/run.py'), - 'editor-states': {loc('../cmd2/README.txt'): {'attrib-starts': [], - 'first-line': 83, - 'folded-linenos': [], - 'sel-line': 132, - 'sel-line-start': 5332, - 'selection_end': 5339, - 'selection_start': 5339}, - loc('README.rst'): {'attrib-starts': [], - 'first-line': 87, - 'folded-linenos': [], - 'sel-line': 98, - 'sel-line-start': 3099, - 'selection_end': 3174, - 'selection_start': 3174}, - loc('examples/writers.ipynb'): {'attrib-starts': [], - 'first-line': 0, - 'folded-linenos': [], - 'sel-line': 0, - 'sel-line-start': 0, - 'selection_end': 0, - 'selection_start': 0}, - loc('setup.py'): {'attrib-starts': [], - 'first-line': 10, - 'folded-linenos': [], - 'sel-line': 24, - 'sel-line-start': 535, - 'selection_end': 568, - 'selection_start': 568}, - loc('src/sql/run.py'): {'attrib-starts': [('Result'\ - 'Set', - 6), + 'sel-line': 84, + 'sel-line-start': 2635, + 'selection_end': 2652, + 'selection_start': 2652}, + 1419831638.277049], + [loc('src/sql/parse.py'), + {'attrib-starts': [], + 'first-line': 0, + 'folded-linenos': [], + 'sel-line': 0, + 'sel-line-start': 0, + 'selection_end': 0, + 'selection_start': 0}, + 1419831640.918957]], + 20), + 'current-loc': loc('src/sql/parse.py'), + 'editor-state-list': [(loc('src/sql/parse.py'), + {'attrib-starts': [], + 'first-line': 1, + 'folded-linenos': [], + 'sel-line': 2, + 'sel-line-start': 52, + 'selection_end': 86, + 'selection_start': 86}), + (loc('README.rst'), + {'attrib-starts': [], + 'first-line': 87, + 'folded-linenos': [], + 'sel-line': 98, + 'sel-line-start': 3099, + 'selection_end': 3174, + 'selection_start': 3174}), + (loc('../cmd2/README.txt'), + {'attrib-starts': [], + 'first-line': 83, + 'folded-linenos': [], + 'sel-line': 132, + 'sel-line-start': 5332, + 'selection_end': 5339, + 'selection_start': 5339}), + (loc('src/sql/run.py'), + {'attrib-starts': [('ResultSet', + 68), ('ResultSet.__init__', - 7)], - 'first-line': 4, - 'folded-linenos': [], - 'sel-line': 15, - 'sel-line-start': 479, - 'selection_end': 497, - 'selection_start': 496}}, - 'has-focus': True, + 74)], + 'first-line': 68, + 'folded-linenos': [], + 'sel-line': 85, + 'sel-line-start': 2645, + 'selection_end': 2652, + 'selection_start': 2652}), + (loc('setup.py'), + {'attrib-starts': [], + 'first-line': 10, + 'folded-linenos': [], + 'sel-line': 24, + 'sel-line-start': 535, + 'selection_end': 568, + 'selection_start': 568}), + (loc('examples/writers.ipynb'), + {'attrib-starts': [], + 'first-line': 0, + 'folded-linenos': [], + 'sel-line': 0, + 'sel-line-start': 0, + 'selection_end': 0, + 'selection_start': 0})], + 'has-focus': False, 'locked': False}, + [loc('src/sql/parse.py'), + loc('README.rst'), + loc('../cmd2/README.txt'), + loc('src/sql/run.py'), + loc('setup.py'), + loc('examples/writers.ipynb')]), 'open_files': [u'../cmd2/README.txt', u'README.rst', u'examples/writers.ipynb', u'setup.py', - u'src/sql/run.py']}, + u'src/sql/run.py', + u'src/sql/parse.py']}, 'saved_notebook_display': None, 'split_percents': {}, 'splits': 1, @@ -679,11 +691,12 @@ guimgr.overall-gui-state = {'windowing-policy': 'combined-window', 'splits': 2, 'tab_location': 'left', 'user_data': {}}, - 'window-alloc': (0, - 27, - 1431, - 813)}]} -guimgr.recent-documents = [loc('src/sql/run.py')] + 'window-alloc': (65, + 24, + 2495, + 1576)}]} +guimgr.recent-documents = [loc('src/sql/parse.py'), + loc('src/sql/run.py')] guimgr.visual-state = {loc('../astropy/astropy/table/table.py'): {'attrib-st'\ 'arts': [('Table', 845), @@ -933,10 +946,11 @@ guimgr.visual-state = {loc('../astropy/astropy/table/table.py'): {'attrib-st'\ proj.build-cmd = {None: ('default', None)} proj.env-vars = {None: ('default', - [''])} + [u''])} proj.pyexec = {None: ('custom', - '/home/catherine/ve/ipy/bin/python')} -search.search-history = [u'sys', + u'/home/catherine/ve/ipy3/bin/python')} +search.search-history = [u'//', + u'sys', u'ip', u'texttable', u'True', diff --git a/src/sql/run.py b/src/sql/run.py index 78585c4..ee758cb 100644 --- a/src/sql/run.py +++ b/src/sql/run.py @@ -6,6 +6,7 @@ import six from six.moves import cStringIO import codecs import os.path +import re import sqlalchemy import sqlparse import prettytable @@ -65,11 +66,25 @@ class CsvResultDescriptor(object): return 'CSV results at %s' % os.path.join(os.path.abspath('.'), self.file_path) def _repr_html_(self): return 'CSV results' % os.path.join('.', 'files', self.file_path) - + + +def _nonbreaking_spaces(match_obj): + """ + Make spaces visible in HTML by replacing all `` `` with `` `` + + Call with a ``re`` match object. Retain group 1, replace group 2 + with nonbreaking speaces. + """ + spaces = ' ' * len(match_obj.group(2)) + return '%s%s' % (match_obj.group(1), spaces) + +_cell_with_spaces_pattern = re.compile(r'()( {2,})') + + class ResultSet(list, ColumnGuesserMixin): """ Results of a SQL query. - + Can access rows listwise, or by string value of leftmost column. """ def __init__(self, sqlaproxy, sql, config): @@ -94,8 +109,10 @@ class ResultSet(list, ColumnGuesserMixin): list.__init__(self, []) self.pretty = None def _repr_html_(self): + _cell_with_spaces_pattern = re.compile(r'()( {2,})') if self.pretty: result = self.pretty.get_html_string() + result = _cell_with_spaces_pattern.sub(_nonbreaking_spaces, result) if self.config.displaylimit and len(self) > self.config.displaylimit: result = '%s\n%d rows, truncated to displaylimit of %d' % ( result, len(self), self.config.displaylimit) @@ -125,23 +142,23 @@ class ResultSet(list, ColumnGuesserMixin): return frame def pie(self, key_word_sep=" ", title=None, **kwargs): """Generates a pylab pie chart from the result set. - + ``matplotlib`` must be installed, and in an IPython Notebook, inlining must be on:: - + %%matplotlib inline - - Values (pie slice sizes) are taken from the + + Values (pie slice sizes) are taken from the rightmost column (numerical values required). All other columns are used to label the pie slices. - + Parameters ---------- key_word_sep: string used to separate column values from each other in pie labels title: Plot title, defaults to name of value column - Any additional keyword arguments will be passsed + Any additional keyword arguments will be passsed through to ``matplotlib.pylab.pie``. """ self.guess_pie_columns(xlabel_sep=key_word_sep) @@ -149,23 +166,23 @@ class ResultSet(list, ColumnGuesserMixin): pie = plt.pie(self.ys[0], labels=self.xlabels, **kwargs) plt.title(title or self.ys[0].name) return pie - + def plot(self, title=None, **kwargs): """Generates a pylab plot from the result set. - + ``matplotlib`` must be installed, and in an IPython Notebook, inlining must be on:: - + %%matplotlib inline - + The first and last columns are taken as the X and Y values. Any columns between are ignored. - + Parameters ---------- title: Plot title, defaults to names of Y value columns - Any additional keyword arguments will be passsed + Any additional keyword arguments will be passsed through to ``matplotlib.pylab.plot``. """ import matplotlib.pylab as plt @@ -179,25 +196,25 @@ class ResultSet(list, ColumnGuesserMixin): plt.title(title or ylabel) plt.ylabel(ylabel) return plot - + def bar(self, key_word_sep = " ", title=None, **kwargs): """Generates a pylab bar plot from the result set. - + ``matplotlib`` must be installed, and in an IPython Notebook, inlining must be on:: - + %%matplotlib inline - + The last quantitative column is taken as the Y values; - all other columns are combined to label the X axis. - + all other columns are combined to label the X axis. + Parameters ---------- title: Plot title, defaults to names of Y value columns key_word_sep: string used to separate column values from each other in labels - - Any additional keyword arguments will be passsed + + Any additional keyword arguments will be passsed through to ``matplotlib.pylab.bar``. """ import matplotlib.pylab as plt @@ -208,8 +225,8 @@ class ResultSet(list, ColumnGuesserMixin): rotation=45) plt.xlabel(self.xlabel) plt.ylabel(self.ys[0].name) - return plot - + return plot + def csv(self, filename=None, **format_params): """Generate results in comma-separated form. Write to ``filename`` if given. Any other parameterw will be passed on to csv.writer.""" @@ -228,8 +245,8 @@ class ResultSet(list, ColumnGuesserMixin): return CsvResultDescriptor(filename) else: return outfile.getvalue() - - + + def interpret_rowcount(rowcount): if rowcount < 0: result = 'Done.' @@ -253,4 +270,3 @@ def run(conn, sql, config, user_namespace): #returning only last result, intentionally else: return 'Connected: %s' % conn.name - \ No newline at end of file