diff -Nru sqlparse-0.1.2/CHANGES sqlparse-0.1.3/CHANGES --- sqlparse-0.1.2/CHANGES 2010-11-23 05:21:37.000000000 +0000 +++ sqlparse-0.1.3/CHANGES 2011-07-29 19:39:31.000000000 +0000 @@ -1,5 +1,30 @@ +Release 0.1.3 (Jul 29, 2011) +---------------------------- + +Bug Fixes + * Improve parsing of floats (thanks to Kris). + * When formatting a statement a space before LIMIT was removed (issue35). + * Fix strip_comments flag (issue38, reported by ooberm...@gmail.com). + * Avoid parsing names as keywords (issue39, reported by djo...@taket.org). + * Make sure identifier lists in subselects are grouped (issue40, + reported by djo...@taket.org). + * Split statements with IF as functions correctly (issue33 and + issue29, reported by charles....@unige.ch). + * Relax detection of keywords, esp. when used as function names + (issue36, nyuhu...@gmail.com). + * Don't treat single characters as keywords (issue32). + * Improve parsing of stand-alone comments (issue26). + * Detection of placeholders in paramterized queries (issue22, + reported by Glyph Lefkowitz). + * Add parsing of MS Access column names with braces (issue27, + reported by frankz...@gmail.com). + +Other + * Replace Django by Flask in App Engine frontend (issue11). + + Release 0.1.2 (Nov 23, 2010) ---------------------------------- +---------------------------- Bug Fixes * Fixed incorrect detection of keyword fragments embed in names (issue7, diff -Nru sqlparse-0.1.2/debian/changelog sqlparse-0.1.3/debian/changelog --- sqlparse-0.1.2/debian/changelog 2011-04-23 08:50:35.000000000 +0000 +++ sqlparse-0.1.3/debian/changelog 2011-09-05 20:28:00.000000000 +0000 @@ -1,3 +1,14 @@ +sqlparse (0.1.3-1) unstable; urgency=low + + * New upstream version. + * Fix debian/watch. + * Bump Standards-Version to 3.9.2. + * Manpage migrated into upstream, using it. + * Include HTML documentation generated with Sphinx rather than .rst files. + * debian/copyright: switch to DEP-5 format. + + -- Andriy Senkovych Fri, 02 Sep 2011 20:23:43 +0300 + sqlparse (0.1.2-2) unstable; urgency=low * Team upload. diff -Nru sqlparse-0.1.2/debian/control sqlparse-0.1.3/debian/control --- sqlparse-0.1.2/debian/control 2010-12-16 20:40:36.000000000 +0000 +++ sqlparse-0.1.3/debian/control 2011-09-05 20:28:00.000000000 +0000 @@ -3,8 +3,8 @@ Priority: optional Maintainer: Andriy Senkovych Uploaders: Debian Python Modules Team -Build-Depends: debhelper (>= 7.0.50~), python-all (>= 2.6.5-13~) -Standards-Version: 3.9.1 +Build-Depends: debhelper (>= 7.0.50~), python-all (>= 2.6.5-13~), python-sphinx (>= 0.6.6-3) +Standards-Version: 3.9.2 Homepage: http://code.google.com/p/python-sqlparse/ Vcs-Svn: svn://svn.debian.org/python-modules/packages/sqlparse/trunk Vcs-Browser: http://svn.debian.org/viewsvn/python-modules/packages/sqlparse/trunk/ @@ -12,7 +12,7 @@ Package: python-sqlparse Architecture: all -Depends: ${misc:Depends}, ${python:Depends} +Depends: ${misc:Depends}, ${python:Depends}, ${sphinxdoc:Depends} Breaks: ${python:Breaks} Description: non-validating SQL parser for Python Sqlparse is a library which provides support for parsing, splitting and diff -Nru sqlparse-0.1.2/debian/copyright sqlparse-0.1.3/debian/copyright --- sqlparse-0.1.2/debian/copyright 2010-12-08 11:32:00.000000000 +0000 +++ sqlparse-0.1.3/debian/copyright 2011-09-05 20:28:00.000000000 +0000 @@ -1,47 +1,45 @@ -This work was packaged for Debian by: - - Andriy Senkovych on Mon, 29 Nov 2010 16:36:21 +0200 - -It was downloaded from: - - http://code.google.com/p/python-sqlparse/ - -Upstream Author(s): - - Andi Albrecht - -Copyright: - - Copyright (c) 2009 Andi Albrecht - -License: - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the authors nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -The Debian packaging is: - - Copyright (C) 2010 Andriy Senkovych - -and is licensed under the GPL License, see "/usr/share/common-licenses/GPL". +Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=173&sc=0 +Upstream-Name: python-sqlparse +Upstream-Contact: Andi Albrecht +Source: http://code.google.com/p/python-sqlparse/downloads/list + +Files: * +Copyright: 2009 Andi Albrecht +License: New BSD License + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the authors nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Files: debian/* +Copyright: 2010 Andriy Senkovych +License: GPL-2 + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + . + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + . + On Debian systems, the full text of the GNU General Public + License version 2 can be found in the file + `/usr/share/common-licenses/GPL-2'. diff -Nru sqlparse-0.1.2/debian/python-sqlparse.docs sqlparse-0.1.3/debian/python-sqlparse.docs --- sqlparse-0.1.2/debian/python-sqlparse.docs 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/debian/python-sqlparse.docs 2011-09-05 20:28:00.000000000 +0000 @@ -0,0 +1 @@ +docs/build/html diff -Nru sqlparse-0.1.2/debian/python-sqlparse.install sqlparse-0.1.3/debian/python-sqlparse.install --- sqlparse-0.1.2/debian/python-sqlparse.install 2010-12-16 20:31:03.000000000 +0000 +++ sqlparse-0.1.3/debian/python-sqlparse.install 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -docs/source/*.rst /usr/share/doc/python-sqlparse/rst diff -Nru sqlparse-0.1.2/debian/python-sqlparse.manpages sqlparse-0.1.3/debian/python-sqlparse.manpages --- sqlparse-0.1.2/debian/python-sqlparse.manpages 2010-12-09 18:41:47.000000000 +0000 +++ sqlparse-0.1.3/debian/python-sqlparse.manpages 2011-09-05 20:28:00.000000000 +0000 @@ -1 +1 @@ -debian/sqlformat.1 +docs/sqlformat.1 diff -Nru sqlparse-0.1.2/debian/rules sqlparse-0.1.3/debian/rules --- sqlparse-0.1.2/debian/rules 2010-12-16 20:31:03.000000000 +0000 +++ sqlparse-0.1.3/debian/rules 2011-09-06 18:28:37.000000000 +0000 @@ -1,7 +1,7 @@ #!/usr/bin/make -f %: - dh $@ --with python2 --buildsystem python_distutils + dh $@ --with python2 --with sphinxdoc --buildsystem python_distutils override_dh_auto_test: ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS))) @@ -11,6 +11,12 @@ done endif -override_dh_compress: - # Document files got accidentally compressed, excluding these files - dh_compress -X.rst +override_dh_clean: + rm -fR docs/build + dh_clean + +build: build-indep +build-indep: docs/build/html + +docs/build/html: + cd docs && $(MAKE) html diff -Nru sqlparse-0.1.2/debian/sqlformat.1 sqlparse-0.1.3/debian/sqlformat.1 --- sqlparse-0.1.2/debian/sqlformat.1 2010-12-16 20:31:03.000000000 +0000 +++ sqlparse-0.1.3/debian/sqlformat.1 1970-01-01 00:00:00.000000000 +0000 @@ -1,63 +0,0 @@ -.\" Based on template /usr/share/man-db/examples/manpage.example provided by -.\" Tom Christiansen . -.TH SQLFORMAT "1" "December 2010" "python-sqlparse version: 0.1.2" "User Commands" -.SH NAME -sqlformat \- reformat SQL -.SH SYNOPSIS -.PP -.B sqlformat -[ -.I "OPTION" -] ... [ -.I "FILE" -] ... -.SH DESCRIPTION -.\" Putting a newline after each sentence can generate better output. -The `sqlformat' command-line tool can be used to reformat SQL file according to -specified options or prepare a snippet in in some programming language (only -Python and PHP currently supported). -Use "-" for -.I FILE -to read from stdin. -.SH OPTIONS -.TP -\fB\-i\fR \fICHOICE\fR|\fB\-\-identifiers\fR=\fIFORMAT\fR -Change case of identifiers. -.I FORMAT -is one of "upper", "lower", "capitalize". -.TP -\fB\-k\fR \fICHOICE\fR|\fB\-\-keywords\fR=\fIFORMAT\fR -Change case of keywords. -.I FORMAT -is one of "upper", "lower", "capitalize". -.TP -\fB\-l\fR \fICHOICE\fR|\fB\-\-language\fR=\fILANG\fR -Output a snippet in programming language LANG. -.I LANG -can be "python", "php". -.TP -\fB\-o\fR \fIFILE\fR|\fB\-\-outfile\fR=\fIFILE\fR -Write output to -.I FILE -(defaults to stdout). -.TP -.BR \-r | \-\-reindent -Reindent statements. -.TP -\fB\-\-indent_width\fR=\fIINDENT_WIDTH\fR -Set indent width to -.IR INDENT_WIDTH . -Default is 2 spaces. -.TP -\fB\-\-strip\-comments -Remove comments. -.TP -.BR \-h | \-\-help -Print a short help message and exit. -All subsequent options are ignored. -.TP -.BR --verbose -Verbose output. -.TP -.BR \-\-version -Print program's version number and exit. diff -Nru sqlparse-0.1.2/debian/watch sqlparse-0.1.3/debian/watch --- sqlparse-0.1.2/debian/watch 2010-12-08 11:32:00.000000000 +0000 +++ sqlparse-0.1.3/debian/watch 2011-06-29 18:12:44.000000000 +0000 @@ -1,2 +1,4 @@ version=3 -http://code.google.com/p/python-sqlparse/downloads/list .*/sqlparse-(.*)\.tar\.gz +opts=downloadurlmangle=s/.*\/\//http:\/\// \ + http://code.google.com/p/python-sqlparse/downloads/list \ + .*\/sqlparse-(.*)\.tar\.gz diff -Nru sqlparse-0.1.2/docs/agogo/layout.html sqlparse-0.1.3/docs/agogo/layout.html --- sqlparse-0.1.2/docs/agogo/layout.html 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/agogo/layout.html 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,237 @@ +{%- block doctype -%} + +{%- endblock %} +{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %} +{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %} + +{%- macro relbar() %} + + {%- endmacro %} + + {%- macro sidebar() %} + {%- if not embedded %}{% if not theme_nosidebar|tobool %} +
+
+ {%- block sidebarlogo %} + {%- if logo %} + + {%- endif %} + {%- endblock %} + {%- block sidebartoc %} + {%- if display_toc %} +

{{ _('Table Of Contents') }}

+ {{ toc }} + {%- endif %} + {%- endblock %} + {%- block sidebarrel %} + {%- if prev %} +

{{ _('Previous topic') }}

+

{{ prev.title }}

+ {%- endif %} + {%- if next %} +

{{ _('Next topic') }}

+

{{ next.title }}

+ {%- endif %} + {%- endblock %} + {%- block sidebarsourcelink %} + {%- if show_source and has_source and sourcename %} +

{{ _('This Page') }}

+ + {%- endif %} + {%- endblock %} + {%- if customsidebar %} + {% include customsidebar %} + {%- endif %} + {%- block sidebarsearch %} + {%- if pagename != "search" %} + + + {%- endif %} + {%- endblock %} +
+
+ {%- endif %}{% endif %} + {%- endmacro %} + + + + + {{ metatags }} + {%- if not embedded %} + {%- set titlesuffix = " — "|safe + docstitle|e %} + {%- else %} + {%- set titlesuffix = "" %} + {%- endif %} + {{ title|striptags }}{{ titlesuffix }} + + + {%- if not embedded %} + + {%- for scriptfile in script_files %} + + {%- endfor %} + {%- if use_opensearch %} + + {%- endif %} + {%- if favicon %} + + {%- endif %} + {%- endif %} + {%- block linktags %} + {%- if hasdoc('about') %} + + {%- endif %} + {%- if hasdoc('genindex') %} + + {%- endif %} + {%- if hasdoc('search') %} + + {%- endif %} + {%- if hasdoc('copyright') %} + + {%- endif %} + + {%- if parents %} + + {%- endif %} + {%- if next %} + + {%- endif %} + {%- if prev %} + + {%- endif %} + {%- endblock %} + {%- block extrahead %} {% endblock %} + + + +
+
+

{{ shorttitle|e }}

+
+ {%- for rellink in rellinks %} + {{ rellink[3] }} + {%- if not loop.last %}{{ reldelim2 }}{% endif %} + {%- endfor %} +
+
+
+ +
+
+
+ {%- block document %} +
+ {%- if not embedded %}{% if not theme_nosidebar|tobool %} +
+ {%- endif %}{% endif %} +
+ {% block body %} {% endblock %} +
+ {%- if not embedded %}{% if not theme_nosidebar|tobool %} +
+ {%- endif %}{% endif %} +
+ {%- endblock %} +
+ +
+
+
+ + + + + diff -Nru sqlparse-0.1.2/docs/agogo/static/agogo.css_t sqlparse-0.1.3/docs/agogo/static/agogo.css_t --- sqlparse-0.1.2/docs/agogo/static/agogo.css_t 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/agogo/static/agogo.css_t 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,328 @@ +* { + margin: 0px; + padding: 0px; +} + +body { + font-family: {{ theme_bodyfont }}; + line-height: 1.4em; + font-size: 14px; + color: black; + background-color: {{ theme_bgcolor }}; +} + + +/* Page layout */ + +div.header, div.content, div.footer { + width: {{ theme_pagewidth }}; + margin-left: auto; + margin-right: auto; +} + +div.header-wrapper { + background: {{ theme_headerbg }}; + border-bottom: 3px solid #2e3436; +} + + +/* Default body styles */ +a { + text-decoration: none; + color: {{ theme_linkcolor }}; +} + +.clearer { + clear: both; +} + +.left { + float: left; +} + +.right { + float: right; +} + +h1, h2, h3, h4 { + font-family: {{ theme_headerfont }}; + font-weight: normal; + color: {{ theme_headercolor2 }}; + margin-bottom: .8em; +} + +h1 { + color: {{ theme_headercolor1 }}; +} + +h2 { + padding-bottom: .5em; + border-bottom: 1px solid {{ theme_headercolor2 }}; +} + +a.headerlink { + visibility: hidden; + color: #dddddd; + padding-left: .3em; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + + + +/* Header */ + +div.header { + padding-top: 10px; + padding-bottom: 10px; +} + +div.header h1 { + font-family: {{ theme_headerfont }}; + font-weight: normal; + font-size: 160%; + letter-spacing: .08em; +} + +div.header h1 a { + color: white; +} + +div.header div.rel { + margin-top: 1em; +} + +div.header div.rel a { + color: {{ theme_headerlinkcolor }}; + letter-spacing: .1em; + text-transform: uppercase; +} + + +/* Content */ +div.content-wrapper { + background-color: white; + padding-top: 20px; + padding-bottom: 20px; +} + +div.document { + width: {{ theme_documentwidth }}; + float: left; +} + +div.body { + padding-right: 2em; + text-align: justify; +} + +div.document ul { + margin-left: 1.2em; + list-style-type: square; +} + +div.document dd { + margin-left: 1.2em; + margin-top: .4em; + margin-bottom: 1em; +} + +div.document .section { + margin-top: 1.7em; +} +div.document .section:first-child { + margin-top: 0px; +} + +div.document div.highlight { + padding: 3px; + background-color: #eeeeec; + border-top: 2px solid #dddddd; + border-bottom: 2px solid #dddddd; + margin-top: .8em; + margin-bottom: .8em; +} + +div.document h2 { + margin-top: .7em; +} + +div.document p { + margin-bottom: .5em; +} + +div.document li.toctree-l1 { + margin-bottom: 1em; +} + +div.document .descname { + font-weight: bold; +} + +div.document .docutils.literal { + background-color: #eeeeec; + padding: 1px; +} + +div.document .docutils.xref.literal { + background-color: transparent; + padding: 0px; +} + + +/* Sidebar */ + +div.sidebar { + width: {{ theme_sidebarwidth }}; + float: right; + font-size: .9em; +} + +div.sidebar h3 { + color: #2e3436; + text-transform: uppercase; + font-size: 130%; + letter-spacing: .1em; +} + +div.sidebar ul { + list-style-type: none; +} + +div.sidebar li.toctree-l1 a { + display: block; + padding: 1px; + border: 1px solid #dddddd; + background-color: #eeeeec; + margin-bottom: .4em; + padding-left: 3px; + color: #2e3436; +} + +div.sidebar li.toctree-l2 a { + background-color: transparent; + border: none; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l2:last-child a { + border-bottom: none; +} + +div.sidebar li.toctree-l1.current a { + border-right: 5px solid {{ theme_headerlinkcolor }}; +} + +div.sidebar li.toctree-l1.current li.toctree-l2 a { + border-right: none; +} + + +/* Footer */ + +div.footer-wrapper { + background: {{ theme_footerbg }}; + border-top: 4px solid #babdb6; + padding-top: 10px; + padding-bottom: 10px; + min-height: 80px; +} + +div.footer, div.footer a { + color: #888a85; +} + +div.footer .right { + text-align: right; +} + +div.footer .left { + text-transform: uppercase; +} + + +/* Styles copied form basic theme */ + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + Binary files /tmp/BTd3Tb5MD3/sqlparse-0.1.2/docs/agogo/static/bgfooter.png and /tmp/pqgMwd5h86/sqlparse-0.1.3/docs/agogo/static/bgfooter.png differ Binary files /tmp/BTd3Tb5MD3/sqlparse-0.1.2/docs/agogo/static/bgtop.png and /tmp/pqgMwd5h86/sqlparse-0.1.3/docs/agogo/static/bgtop.png differ diff -Nru sqlparse-0.1.2/docs/agogo/theme.conf sqlparse-0.1.3/docs/agogo/theme.conf --- sqlparse-0.1.2/docs/agogo/theme.conf 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/agogo/theme.conf 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,18 @@ +[theme] +inherit = basic +stylesheet = agogo.css +pygments_style = tango + +[options] +bodyfont = "Verdana", Arial, sans-serif +headerfont = "Georgia", "Times New Roman", serif +pagewidth = 70em +documentwidth = 50em +sidebarwidth = 20em +bgcolor = #eeeeec +headerbg = url(bgtop.png) top left repeat-x +footerbg = url(bgfooter.png) top left repeat-x +linkcolor = #ce5c00 +headercolor1 = #204a87 +headercolor2 = #3465a4 +headerlinkcolor = #fcaf3e \ No newline at end of file diff -Nru sqlparse-0.1.2/docs/Makefile sqlparse-0.1.3/docs/Makefile --- sqlparse-0.1.2/docs/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/Makefile 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,88 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf build/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html + @echo + @echo "Build finished. The HTML pages are in build/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) build/dirhtml + @echo + @echo "Build finished. The HTML pages are in build/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in build/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) build/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in build/qthelp, like this:" + @echo "# qcollectiongenerator build/qthelp/python-sqlparse.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile build/qthelp/python-sqlparse.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex + @echo + @echo "Build finished; the LaTeX files are in build/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes + @echo + @echo "The overview file is in build/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in build/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) build/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in build/doctest/output.txt." diff -Nru sqlparse-0.1.2/docs/source/conf.py sqlparse-0.1.3/docs/source/conf.py --- sqlparse-0.1.2/docs/source/conf.py 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/source/conf.py 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,200 @@ +# -*- coding: utf-8 -*- +# +# python-sqlparse documentation build configuration file, created by +# sphinx-quickstart on Thu Feb 26 08:19:28 2009. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import datetime +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../')) + +import sqlparse + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', + 'sphinx.ext.autosummary'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'python-sqlparse' +copyright = u'%s, Andi Albrecht' % datetime.date.today().strftime('%Y') + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = sqlparse.__version__ +# The full version, including alpha/beta/rc tags. +release = sqlparse.__version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'tango' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'agogo' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = [os.path.abspath('../')] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-sqlparsedoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'python-sqlparse.tex', ur'python-sqlparse Documentation', + ur'Andi Albrecht', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True +todo_include_todos = True diff -Nru sqlparse-0.1.2/docs/sqlformat.1 sqlparse-0.1.3/docs/sqlformat.1 --- sqlparse-0.1.2/docs/sqlformat.1 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/docs/sqlformat.1 2011-03-02 04:39:35.000000000 +0000 @@ -0,0 +1,65 @@ +.\" Based on template /usr/share/man-db/examples/manpage.example provided by +.\" Tom Christiansen . +.TH SQLFORMAT "1" "December 2010" "python-sqlparse version: 0.1.2" "User Commands" +.SH NAME +sqlformat \- reformat SQL +.SH SYNOPSIS +.PP +.B sqlformat +[ +.I "OPTION" +] ... [ +.I "FILE" +] ... +.SH DESCRIPTION +.\" Putting a newline after each sentence can generate better output. +The `sqlformat' command-line tool can be used to reformat SQL file according to +specified options or prepare a snippet in in some programming language (only +Python and PHP currently supported). +Use "-" for +.I FILE +to read from stdin. +.SH OPTIONS +.TP +\fB\-i\fR \fICHOICE\fR|\fB\-\-identifiers\fR=\fIFORMAT\fR +Change case of identifiers. +.I FORMAT +is one of "upper", "lower", "capitalize". +.TP +\fB\-k\fR \fICHOICE\fR|\fB\-\-keywords\fR=\fIFORMAT\fR +Change case of keywords. +.I FORMAT +is one of "upper", "lower", "capitalize". +.TP +\fB\-l\fR \fICHOICE\fR|\fB\-\-language\fR=\fILANG\fR +Output a snippet in programming language LANG. +.I LANG +can be "python", "php". +.TP +\fB\-o\fR \fIFILE\fR|\fB\-\-outfile\fR=\fIFILE\fR +Write output to +.I FILE +(defaults to stdout). +.TP +.BR \-r | \-\-reindent +Reindent statements. +.TP +\fB\-\-indent_width\fR=\fIINDENT_WIDTH\fR +Set indent width to +.IR INDENT_WIDTH . +Default is 2 spaces. +.TP +\fB\-\-strip\-comments +Remove comments. +.TP +.BR \-h | \-\-help +Print a short help message and exit. +All subsequent options are ignored. +.TP +.BR --verbose +Verbose output. +.TP +.BR \-\-version +Print program's version number and exit. +.SH AUTHORS +This man page was written by Andriy Senkovych diff -Nru sqlparse-0.1.2/PKG-INFO sqlparse-0.1.3/PKG-INFO --- sqlparse-0.1.2/PKG-INFO 2010-11-23 05:26:53.000000000 +0000 +++ sqlparse-0.1.3/PKG-INFO 2011-07-29 19:40:08.000000000 +0000 @@ -1,12 +1,12 @@ Metadata-Version: 1.0 Name: sqlparse -Version: 0.1.2 +Version: 0.1.3 Summary: Non-validating SQL parser Home-page: http://python-sqlparse.googlecode.com/ Author: Andi Albrecht Author-email: albrecht.andi@gmail.com License: BSD -Download-URL: http://python-sqlparse.googlecode.com/files/sqlparse-0.1.2.tar.gz +Download-URL: http://python-sqlparse.googlecode.com/files/sqlparse-0.1.3.tar.gz Description: ``sqlparse`` is a non-validating SQL parser module. It provides support for parsing, splitting and formatting SQL statements. diff -Nru sqlparse-0.1.2/sqlparse/engine/filter.py sqlparse-0.1.3/sqlparse/engine/filter.py --- sqlparse-0.1.2/sqlparse/engine/filter.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/engine/filter.py 2011-07-23 22:34:37.000000000 +0000 @@ -21,11 +21,13 @@ self._in_declare = False self._in_dbldollar = False self._is_create = False + self._begin_depth = 0 def _reset(self): self._in_declare = False self._in_dbldollar = False self._is_create = False + self._begin_depth = 0 def _change_splitlevel(self, ttype, value): # PostgreSQL @@ -51,6 +53,7 @@ return 1 if unified == 'BEGIN': + self._begin_depth += 1 if self._in_declare: # FIXME(andi): This makes no sense. return 0 return 0 @@ -58,12 +61,14 @@ if unified == 'END': # Should this respect a preceeding BEGIN? # In CASE ... WHEN ... END this results in a split level -1. + self._begin_depth = max(0, self._begin_depth-1) return -1 if ttype is T.Keyword.DDL and unified.startswith('CREATE'): self._is_create = True + return 0 - if unified in ('IF', 'FOR') and self._is_create: + if unified in ('IF', 'FOR') and self._is_create and self._begin_depth > 0: return 1 # Default diff -Nru sqlparse-0.1.2/sqlparse/engine/grouping.py sqlparse-0.1.3/sqlparse/engine/grouping.py --- sqlparse-0.1.2/sqlparse/engine/grouping.py 2010-11-23 04:52:49.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/engine/grouping.py 2011-07-23 22:07:05.000000000 +0000 @@ -170,11 +170,12 @@ def group_identifier_list(tlist): [group_identifier_list(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, (sql.Identifier, sql.IdentifierList))] + if not isinstance(sgroup, sql.IdentifierList)] idx = 0 # Allowed list items - fend1_funcs = [lambda t: isinstance(t, sql.Identifier), + fend1_funcs = [lambda t: isinstance(t, (sql.Identifier, sql.Function)), lambda t: t.is_whitespace(), + lambda t: t.ttype == T.Name, lambda t: t.ttype == T.Wildcard, lambda t: t.match(T.Keyword, 'null'), lambda t: t.ttype == T.Number.Integer, @@ -253,25 +254,26 @@ else: end = tlist.tokens[tlist.token_index(end) - 1] group = tlist.group_tokens(sql.Where, - tlist.tokens_between(token, end)) + tlist.tokens_between(token, end), + ignore_ws=True) idx = tlist.token_index(group) token = tlist.token_next_match(idx, T.Keyword, 'WHERE') def group_aliased(tlist): [group_aliased(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, sql.Identifier)] + if not isinstance(sgroup, (sql.Identifier, sql.Function))] idx = 0 - token = tlist.token_next_by_instance(idx, sql.Identifier) + token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) while token: next_ = tlist.token_next(tlist.token_index(token)) - if next_ is not None and isinstance(next_, sql.Identifier): + if next_ is not None and isinstance(next_, (sql.Identifier, sql.Function)): grp = tlist.tokens_between(token, next_)[1:] token.tokens.extend(grp) for t in grp: tlist.tokens.remove(t) idx = tlist.token_index(token) + 1 - token = tlist.token_next_by_instance(idx, sql.Identifier) + token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) def group_typecasts(tlist): diff -Nru sqlparse-0.1.2/sqlparse/filters.py sqlparse-0.1.3/sqlparse/filters.py --- sqlparse-0.1.2/sqlparse/filters.py 2010-11-22 19:09:50.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/filters.py 2011-07-29 04:06:34.000000000 +0000 @@ -57,10 +57,16 @@ class StripCommentsFilter(Filter): + def _get_next_comment(self, tlist): + # TODO(andi) Comment types should be unified, see related issue38 + token = tlist.token_next_by_instance(0, sql.Comment) + if token is None: + token = tlist.token_next_by_type(0, T.Comment) + return token + def _process(self, tlist): - clss = set([x.__class__ for x in tlist.tokens]) - while sql.Comment in clss: - token = tlist.token_next_by_instance(0, sql.Comment) + token = self._get_next_comment(tlist) + while token: tidx = tlist.token_index(token) prev = tlist.token_prev(tidx, False) next_ = tlist.token_next(tidx, False) @@ -73,7 +79,7 @@ tlist.tokens[tidx] = sql.Token(T.Whitespace, ' ') else: tlist.tokens.pop(tidx) - clss = set([x.__class__ for x in tlist.tokens]) + token = self._get_next_comment(tlist) def process(self, stack, stmt): [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] @@ -227,8 +233,9 @@ self.offset += outer_offset for cond, value in tlist.get_cases(): if is_first: + tcond = list(cond[0].flatten())[0] is_first = False - num_offset = self._get_offset(cond[0]) - len(cond[0].value) + num_offset = self._get_offset(tcond) - len(tcond.value) self.offset += num_offset continue if cond is None: diff -Nru sqlparse-0.1.2/sqlparse/__init__.py sqlparse-0.1.3/sqlparse/__init__.py --- sqlparse-0.1.2/sqlparse/__init__.py 2010-11-23 05:21:37.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/__init__.py 2011-07-29 19:40:07.000000000 +0000 @@ -6,7 +6,7 @@ """Parse SQL statements.""" -__version__ = '0.1.2' +__version__ = '0.1.3' class SQLParseError(Exception): diff -Nru sqlparse-0.1.2/sqlparse/keywords.py sqlparse-0.1.3/sqlparse/keywords.py --- sqlparse-0.1.2/sqlparse/keywords.py 2010-11-23 04:53:57.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/keywords.py 2011-07-26 03:26:20.000000000 +0000 @@ -172,7 +172,7 @@ 'FULL': tokens.Keyword, 'FUNCTION': tokens.Keyword, - 'G': tokens.Keyword, +# 'G': tokens.Keyword, 'GENERAL': tokens.Keyword, 'GENERATED': tokens.Keyword, 'GET': tokens.Keyword, @@ -219,7 +219,7 @@ 'ISOLATION': tokens.Keyword, 'ITERATE': tokens.Keyword, - 'K': tokens.Keyword, +# 'K': tokens.Keyword, 'KEY': tokens.Keyword, 'KEY_MEMBER': tokens.Keyword, 'KEY_TYPE': tokens.Keyword, @@ -244,7 +244,7 @@ 'LOCK': tokens.Keyword, 'LOWER': tokens.Keyword, - 'M': tokens.Keyword, +# 'M': tokens.Keyword, 'MAP': tokens.Keyword, 'MATCH': tokens.Keyword, 'MAXVALUE': tokens.Keyword, @@ -343,7 +343,6 @@ 'RELATIVE': tokens.Keyword, 'RENAME': tokens.Keyword, 'REPEATABLE': tokens.Keyword, - 'REPLACE': tokens.Keyword, 'RESET': tokens.Keyword, 'RESTART': tokens.Keyword, 'RESTRICT': tokens.Keyword, @@ -400,7 +399,7 @@ 'SQLERROR': tokens.Keyword, 'SQLEXCEPTION': tokens.Keyword, 'SQLSTATE': tokens.Keyword, - 'SQLWARNINIG': tokens.Keyword, + 'SQLWARNING': tokens.Keyword, 'STABLE': tokens.Keyword, 'START': tokens.Keyword, 'STATE': tokens.Keyword, @@ -528,6 +527,7 @@ 'INSERT': tokens.Keyword.DML, 'DELETE': tokens.Keyword.DML, 'UPDATE': tokens.Keyword.DML, + 'REPLACE': tokens.Keyword.DML, 'DROP': tokens.Keyword.DDL, 'CREATE': tokens.Keyword.DDL, 'ALTER': tokens.Keyword.DDL, diff -Nru sqlparse-0.1.2/sqlparse/lexer.py sqlparse-0.1.3/sqlparse/lexer.py --- sqlparse-0.1.2/sqlparse/lexer.py 2010-11-23 04:54:22.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/lexer.py 2011-07-29 19:16:33.000000000 +0000 @@ -150,7 +150,7 @@ return type.__call__(cls, *args, **kwds) -class Lexer: +class Lexer(object): __metaclass__ = LexerMeta @@ -172,22 +172,29 @@ (r':=', tokens.Assignment), (r'::', tokens.Punctuation), (r'[*]', tokens.Wildcard), + (r'CASE\b', tokens.Keyword), # extended CASE(foo) (r"`(``|[^`])*`", tokens.Name), (r"´(´´|[^´])*´", tokens.Name), + (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', tokens.Name.Builtin), + (r'\?{1}', tokens.Name.Placeholder), + (r'[$:?%][a-zA-Z0-9_]+[^$:?%]?', tokens.Name.Placeholder), (r'@[a-zA-Z_][a-zA-Z0-9_]+', tokens.Name), + (r'[a-zA-Z_][a-zA-Z0-9_]*(?=[.(])', tokens.Name), # see issue39 (r'[<>=~!]+', tokens.Operator.Comparison), (r'[+/@#%^&|`?^-]+', tokens.Operator), + (r'0x[0-9a-fA-F]+', tokens.Number.Hexadecimal), + (r'[0-9]*\.[0-9]+', tokens.Number.Float), (r'[0-9]+', tokens.Number.Integer), # TODO: Backslash escapes? (r"(''|'.*?[^\\]')", tokens.String.Single), # not a real string literal in ANSI SQL: (r'(""|".*?[^\\]")', tokens.String.Symbol), + (r'(\[.*[^\]]\])', tokens.Name), (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN\b', tokens.Keyword), (r'END( IF| LOOP)?\b', tokens.Keyword), (r'NOT NULL\b', tokens.Keyword), (r'CREATE( OR REPLACE)?\b', tokens.Keyword.DDL), (r'[a-zA-Z_][a-zA-Z0-9_]*', is_keyword), - (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', tokens.Name.Builtin), (r'[;:()\[\],\.]', tokens.Punctuation), ], 'multiline-comments': [ diff -Nru sqlparse-0.1.2/sqlparse/sql.py sqlparse-0.1.3/sqlparse/sql.py --- sqlparse-0.1.2/sqlparse/sql.py 2010-11-21 17:56:02.000000000 +0000 +++ sqlparse-0.1.3/sqlparse/sql.py 2011-07-29 04:06:34.000000000 +0000 @@ -79,7 +79,7 @@ return True return False else: - if self.ttype is T.Keyword: + if self.ttype in T.Keyword: values = set([v.upper() for v in values]) return self.value.upper() in values else: @@ -144,19 +144,19 @@ def _get_repr_name(self): return self.__class__.__name__ - ## def _pprint_tree(self, max_depth=None, depth=0): - ## """Pretty-print the object tree.""" - ## indent = ' '*(depth*2) - ## for token in self.tokens: - ## if token.is_group(): - ## pre = ' | ' - ## else: - ## pre = ' | ' - ## print '%s%s%s \'%s\'' % (indent, pre, token._get_repr_name(), - ## token._get_repr_value()) - ## if (token.is_group() and max_depth is not None - ## and depth < max_depth): - ## token._pprint_tree(max_depth, depth+1) + def _pprint_tree(self, max_depth=None, depth=0): + """Pretty-print the object tree.""" + indent = ' '*(depth*2) + for idx, token in enumerate(self.tokens): + if token.is_group(): + pre = ' +-' + else: + pre = ' | ' + print '%s%s%d %s \'%s\'' % (indent, pre, idx, + token._get_repr_name(), + token._get_repr_value()) + if (token.is_group() and (max_depth is None or depth < max_depth)): + token._pprint_tree(max_depth, depth+1) def flatten(self): """Generator yielding ungrouped tokens. @@ -287,16 +287,21 @@ If *exclude_end* is ``True`` (default is ``False``) the end token is included too. """ + # FIXME(andi): rename exclude_end to inlcude_end if exclude_end: offset = 0 else: offset = 1 - return self.tokens[ - self.token_index(start):self.token_index(end) + offset] + end_idx = self.token_index(end) + offset + start_idx = self.token_index(start) + return self.tokens[start_idx:end_idx] - def group_tokens(self, grp_cls, tokens): + def group_tokens(self, grp_cls, tokens, ignore_ws=False): """Replace tokens by an instance of *grp_cls*.""" idx = self.token_index(tokens[0]) + if ignore_ws: + while tokens and tokens[-1].is_whitespace(): + tokens = tokens[:-1] for t in tokens: self.tokens.remove(t) grp = grp_cls(tokens) diff -Nru sqlparse-0.1.2/tests/regressiontests/issue13.py sqlparse-0.1.3/tests/regressiontests/issue13.py --- sqlparse-0.1.2/tests/regressiontests/issue13.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/tests/regressiontests/issue13.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,16 +0,0 @@ -import unittest - -import sqlparse - - -TEST_SQL = """select 'one'; -select 'two\\''; -select 'three';""" - - -class TestIssue13(unittest.TestCase): - - def test_quoted(self): - parsed = sqlparse.parse(TEST_SQL) - self.assertEqual(len(parsed), 3) - self.assertEqual(str(parsed[1]).strip(), "select 'two\\'';") diff -Nru sqlparse-0.1.2/tests/regressiontests/issue9.py sqlparse-0.1.3/tests/regressiontests/issue9.py --- sqlparse-0.1.2/tests/regressiontests/issue9.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/tests/regressiontests/issue9.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -import unittest - -import sqlparse -from sqlparse.sql import Statement, Parenthesis -from sqlparse import tokens as T - - -class TestIssue9(unittest.TestCase): - - def test_where_doesnt_consume_parenthesis(self): - p = sqlparse.parse('(where 1)')[0] - self.assert_(isinstance(p, Statement)) - self.assertEqual(len(p.tokens), 1) - self.assert_(isinstance(p.tokens[0], Parenthesis)) - prt = p.tokens[0] - self.assertEqual(len(prt.tokens), 3) - self.assertEqual(prt.tokens[0].ttype, T.Punctuation) - self.assertEqual(prt.tokens[-1].ttype, T.Punctuation) diff -Nru sqlparse-0.1.2/tests/test_format.py sqlparse-0.1.3/tests/test_format.py --- sqlparse-0.1.2/tests/test_format.py 2010-11-22 19:09:50.000000000 +0000 +++ sqlparse-0.1.3/tests/test_format.py 2011-07-23 22:54:58.000000000 +0000 @@ -186,6 +186,14 @@ ' else 5', 'end'])) + def test_case2(self): + f = lambda sql: sqlparse.format(sql, reindent=True) + s = 'case(foo) when bar = 1 then 2 else 3 end' + self.ndiffAssertEqual(f(s), '\n'.join(['case(foo)', + ' when bar = 1 then 2', + ' else 3', + 'end'])) + def test_nested_identifier_list(self): # issue4 f = lambda sql: sqlparse.format(sql, reindent=True) s = '(foo as bar, bar1, bar2 as bar3, b4 as b5)' @@ -213,6 +221,13 @@ 'where (c1 = 1)', 'order by c1'])) + def test_keywordfunctions(self): # issue36 + f = lambda sql: sqlparse.format(sql, reindent=True) + s = 'select max(a) b, foo, bar' + self.ndiffAssertEqual(f(s), '\n'.join(['select max(a) b,', + ' foo,', + ' bar'])) + diff -Nru sqlparse-0.1.2/tests/test_grouping.py sqlparse-0.1.3/tests/test_grouping.py --- sqlparse-0.1.2/tests/test_grouping.py 2010-11-21 17:55:58.000000000 +0000 +++ sqlparse-0.1.3/tests/test_grouping.py 2011-07-23 21:47:10.000000000 +0000 @@ -157,6 +157,10 @@ self.ndiffAssertEqual(s, p.to_unicode()) self.assertEqual(p.tokens[4].get_alias(), 'view') + def test_idlist_function(self): # see issue10 too + p = sqlparse.parse('foo(1) x, bar')[0] + self.assert_(isinstance(p.tokens[0], sql.IdentifierList)) + def test_comparison_exclude(self): # make sure operators are not handled too lazy p = sqlparse.parse('(=)')[0] diff -Nru sqlparse-0.1.2/tests/test_parse.py sqlparse-0.1.3/tests/test_parse.py --- sqlparse-0.1.2/tests/test_parse.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/tests/test_parse.py 2011-07-29 18:57:47.000000000 +0000 @@ -61,3 +61,44 @@ self.assert_(baz.has_ancestor(p.tokens[-1].tokens[1])) self.assert_(baz.has_ancestor(p.tokens[-1])) self.assert_(baz.has_ancestor(p)) + + def test_float(self): + t = sqlparse.parse('.5')[0].tokens + self.assertEqual(len(t), 1) + self.assert_(t[0].ttype is sqlparse.tokens.Number.Float) + t = sqlparse.parse('.51')[0].tokens + self.assertEqual(len(t), 1) + self.assert_(t[0].ttype is sqlparse.tokens.Number.Float) + t = sqlparse.parse('1.5')[0].tokens + self.assertEqual(len(t), 1) + self.assert_(t[0].ttype is sqlparse.tokens.Number.Float) + t = sqlparse.parse('12.5')[0].tokens + self.assertEqual(len(t), 1) + self.assert_(t[0].ttype is sqlparse.tokens.Number.Float) + + def test_placeholder(self): + def _get_tokens(sql): + return sqlparse.parse(sql)[0].tokens[-1].tokens + t = _get_tokens('select * from foo where user = ?') + self.assert_(t[-1].ttype is sqlparse.tokens.Name.Placeholder) + self.assertEqual(t[-1].value, '?') + t = _get_tokens('select * from foo where user = :1') + self.assert_(t[-1].ttype is sqlparse.tokens.Name.Placeholder) + self.assertEqual(t[-1].value, ':1') + t = _get_tokens('select * from foo where user = :name') + self.assert_(t[-1].ttype is sqlparse.tokens.Name.Placeholder) + self.assertEqual(t[-1].value, ':name') + t = _get_tokens('select * from foo where user = %s') + self.assert_(t[-1].ttype is sqlparse.tokens.Name.Placeholder) + self.assertEqual(t[-1].value, '%s') + t = _get_tokens('select * from foo where user = $a') + self.assert_(t[-1].ttype is sqlparse.tokens.Name.Placeholder) + self.assertEqual(t[-1].value, '$a') + + def test_access_symbol(self): # see issue27 + t = sqlparse.parse('select a.[foo bar] as foo')[0].tokens + self.assert_(isinstance(t[-1], sqlparse.sql.Identifier)) + self.assertEqual(t[-1].get_name(), 'foo') + self.assertEqual(t[-1].get_real_name(), '[foo bar]') + self.assertEqual(t[-1].get_parent_name(), 'a') + diff -Nru sqlparse-0.1.2/tests/test_regressions.py sqlparse-0.1.3/tests/test_regressions.py --- sqlparse-0.1.2/tests/test_regressions.py 1970-01-01 00:00:00.000000000 +0000 +++ sqlparse-0.1.3/tests/test_regressions.py 2011-07-26 03:26:20.000000000 +0000 @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- + +from tests.utils import TestCaseBase + +import sqlparse +from sqlparse import sql +from sqlparse import tokens as T + + +class RegressionTests(TestCaseBase): + + def test_issue9(self): + # make sure where doesn't consume parenthesis + p = sqlparse.parse('(where 1)')[0] + self.assert_(isinstance(p, sql.Statement)) + self.assertEqual(len(p.tokens), 1) + self.assert_(isinstance(p.tokens[0], sql.Parenthesis)) + prt = p.tokens[0] + self.assertEqual(len(prt.tokens), 3) + self.assertEqual(prt.tokens[0].ttype, T.Punctuation) + self.assertEqual(prt.tokens[-1].ttype, T.Punctuation) + + def test_issue13(self): + parsed = sqlparse.parse(("select 'one';\n" + "select 'two\\'';\n" + "select 'three';")) + self.assertEqual(len(parsed), 3) + self.assertEqual(str(parsed[1]).strip(), "select 'two\\'';") + + def test_issue26(self): + # parse stand-alone comments + p = sqlparse.parse('--hello')[0] + self.assertEqual(len(p.tokens), 1) + self.assert_(p.tokens[0].ttype is T.Comment.Single) + p = sqlparse.parse('-- hello')[0] + self.assertEqual(len(p.tokens), 1) + self.assert_(p.tokens[0].ttype is T.Comment.Single) + p = sqlparse.parse('--hello\n')[0] + self.assertEqual(len(p.tokens), 1) + self.assert_(p.tokens[0].ttype is T.Comment.Single) + p = sqlparse.parse('--')[0] + self.assertEqual(len(p.tokens), 1) + self.assert_(p.tokens[0].ttype is T.Comment.Single) + p = sqlparse.parse('--\n')[0] + self.assertEqual(len(p.tokens), 1) + self.assert_(p.tokens[0].ttype is T.Comment.Single) + + def test_issue34(self): + t = sqlparse.parse("create")[0].token_first() + self.assertEqual(t.match(T.Keyword.DDL, "create"), True) + self.assertEqual(t.match(T.Keyword.DDL, "CREATE"), True) + + def test_issue35(self): + # missing space before LIMIT + sql = sqlparse.format("select * from foo where bar = 1 limit 1", + reindent=True) + self.ndiffAssertEqual(sql, "\n".join(["select *", + "from foo", + "where bar = 1 limit 1"])) + + def test_issue38(self): + sql = sqlparse.format("SELECT foo; -- comment", + strip_comments=True) + self.ndiffAssertEqual(sql, "SELECT foo;") + sql = sqlparse.format("/* foo */", strip_comments=True) + self.ndiffAssertEqual(sql, "") + + def test_issue39(self): + p = sqlparse.parse('select user.id from user')[0] + self.assertEqual(len(p.tokens), 7) + idt = p.tokens[2] + self.assertEqual(idt.__class__, sql.Identifier) + self.assertEqual(len(idt.tokens), 3) + self.assertEqual(idt.tokens[0].match(T.Name, 'user'), True) + self.assertEqual(idt.tokens[1].match(T.Punctuation, '.'), True) + self.assertEqual(idt.tokens[2].match(T.Name, 'id'), True) + + def test_issue40(self): + # make sure identifier lists in subselects are grouped + p = sqlparse.parse(('SELECT id, name FROM ' + '(SELECT id, name FROM bar) as foo'))[0] + self.assertEqual(len(p.tokens), 7) + self.assertEqual(p.tokens[2].__class__, sql.IdentifierList) + self.assertEqual(p.tokens[-1].__class__, sql.Identifier) + self.assertEqual(p.tokens[-1].get_name(), u'foo') + sp = p.tokens[-1].tokens[0] + self.assertEqual(sp.tokens[3].__class__, sql.IdentifierList) + # make sure that formatting works as expected + self.ndiffAssertEqual( + sqlparse.format(('SELECT id, name FROM ' + '(SELECT id, name FROM bar)'), + reindent=True), + ('SELECT id,\n' + ' name\n' + 'FROM\n' + ' (SELECT id,\n' + ' name\n' + ' FROM bar)')) + self.ndiffAssertEqual( + sqlparse.format(('SELECT id, name FROM ' + '(SELECT id, name FROM bar) as foo'), + reindent=True), + ('SELECT id,\n' + ' name\n' + 'FROM\n' + ' (SELECT id,\n' + ' name\n' + ' FROM bar) as foo')) diff -Nru sqlparse-0.1.2/tests/test_split.py sqlparse-0.1.3/tests/test_split.py --- sqlparse-0.1.2/tests/test_split.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/tests/test_split.py 2011-07-23 22:36:24.000000000 +0000 @@ -103,3 +103,10 @@ 'SELECT 2;') stmts = sqlparse.split(sql) self.assertEqual(len(stmts), 2) + + def test_if_function(self): # see issue 33 + # don't let IF as a function confuse the splitter + sql = ('CREATE TEMPORARY TABLE tmp SELECT IF(a=1, a, b) AS o FROM one; ' + 'SELECT t FROM two') + stmts = sqlparse.split(sql) + self.assertEqual(len(stmts), 2) diff -Nru sqlparse-0.1.2/tests/utils.py sqlparse-0.1.3/tests/utils.py --- sqlparse-0.1.2/tests/utils.py 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/tests/utils.py 2011-07-29 19:15:49.000000000 +0000 @@ -28,11 +28,12 @@ # Adopted from Python's tests. def ndiffAssertEqual(self, first, second): """Like failUnlessEqual except use ndiff for readable output.""" - if first <> second: + if first != second: sfirst = unicode(first) ssecond = unicode(second) diff = difflib.ndiff(sfirst.splitlines(), ssecond.splitlines()) fp = StringIO() - print >> fp, NL, NL.join(diff) + fp.write(NL) + fp.write(NL.join(diff)) print fp.getvalue() raise self.failureException, fp.getvalue() diff -Nru sqlparse-0.1.2/TODO sqlparse-0.1.3/TODO --- sqlparse-0.1.2/TODO 2010-11-21 07:17:21.000000000 +0000 +++ sqlparse-0.1.3/TODO 2011-03-02 04:39:35.000000000 +0000 @@ -1,4 +1,5 @@ +* Provide a function to replace tokens. See this thread: https://groups.google.com/d/msg/sqlparse/5xmBL2UKqX4/ZX9z_peve-AJ * Fix bugs on issue tracker. * Document filter stack and processing phases. * Rewrite App Engine application using webapp. -* See KnownIssues http://code.google.com/p/python-sqlparse/wiki/KnownIssues \ No newline at end of file +* See KnownIssues http://code.google.com/p/python-sqlparse/wiki/KnownIssues