diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cd7c049..560b4b5 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -9,3 +9,5 @@ search = version="{current_version}" replace = version="{new_version}" [bumpversion:file:dataset/__init__.py] + +[bumpversion:file:docs/conf.py] diff --git a/dataset/table.py b/dataset/table.py index f3f8e3d..9e1aab0 100644 --- a/dataset/table.py +++ b/dataset/table.py @@ -486,9 +486,12 @@ class Table(object): self.create_column(name, type_) def drop_column(self, name): - """Drop the column ``name``. + """ + Drop the column ``name``. :: + table.drop_column('created_at') + """ if self.db.engine.dialect.name == "sqlite": raise RuntimeError("SQLite does not support dropping columns.") @@ -589,9 +592,12 @@ class Table(object): # return all rows sorted by multiple columns (descending by year) results = table.find(order_by=['country', '-year']) - To perform complex queries with advanced filters or to perform - aggregation, use :py:meth:`db.query() ` - instead. + You can also submit filters based on criteria other than equality, + see :ref:`advanced_filters` for details. + + To run more complex queries with JOINs, or to perform GROUP BY-style + aggregation, you can also use :py:meth:`db.query() ` + to run raw SQL queries instead. """ if not self.exists: return iter([]) diff --git a/docs/_static/dataset-logo-dark.png b/docs/_static/dataset-logo-dark.png new file mode 100644 index 0000000..8a5a272 Binary files /dev/null and b/docs/_static/dataset-logo-dark.png differ diff --git a/docs/_static/dataset-logo-light.png b/docs/_static/dataset-logo-light.png new file mode 100644 index 0000000..2feb425 Binary files /dev/null and b/docs/_static/dataset-logo-light.png differ diff --git a/docs/_themes/LICENSE b/docs/_themes/LICENSE deleted file mode 100755 index 3d1e04a..0000000 --- a/docs/_themes/LICENSE +++ /dev/null @@ -1,45 +0,0 @@ -Modifications: - -Copyright (c) 2011 Kenneth Reitz. - - -Original Project: - -Copyright (c) 2010 by Armin Ronacher. - - -Some rights reserved. - -Redistribution and use in source and binary forms of the theme, 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. - -* The names of the contributors may not be used to endorse or - promote products derived from this software without specific - prior written permission. - -We kindly ask you to only use these themes in an unmodified manner just -for Flask and Flask-related products, not for unrelated projects. If you -like the visual style and want to use it for your own projects, please -consider making some larger changes to the themes (such as changing -font faces, sizes, colors or margins). - -THIS THEME 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 THEME, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/_themes/README.md b/docs/_themes/README.md deleted file mode 100755 index 91f0d6d..0000000 --- a/docs/_themes/README.md +++ /dev/null @@ -1,25 +0,0 @@ -krTheme Sphinx Style -==================== - -This repository contains sphinx styles Kenneth Reitz uses in most of -his projects. It is a derivative of Mitsuhiko's themes for Flask and Flask related -projects. To use this style in your Sphinx documentation, follow -this guide: - -1. put this folder as _themes into your docs folder. Alternatively - you can also use git submodules to check out the contents there. - -2. add this to your conf.py: - - sys.path.append(os.path.abspath('_themes')) - html_theme_path = ['_themes'] - html_theme = 'kr' - -The following themes exist: - -**kr** - the standard flask documentation theme for large projects - -**kr_small** - small one-page theme. Intended to be used by very small addon libraries. - diff --git a/docs/_themes/flask_theme_support.py b/docs/_themes/flask_theme_support.py deleted file mode 100755 index 0dcf53b..0000000 --- a/docs/_themes/flask_theme_support.py +++ /dev/null @@ -1,89 +0,0 @@ -# flasky extensions. flasky pygments style based on tango style -from pygments.style import Style -from pygments.token import ( - Keyword, - Name, - Comment, - String, - Error, - Number, - Operator, - Generic, - Whitespace, - Punctuation, - Other, - Literal, -) - - -class FlaskyStyle(Style): - background_color = "#f8f8f8" - default_style = "" - - styles = { - # No corresponding class for the following: - # Text: "", # class: '' - Whitespace: "underline #f8f8f8", # class: 'w' - Error: "#a40000 border:#ef2929", # class: 'err' - Other: "#000000", # class 'x' - Comment: "italic #8f5902", # class: 'c' - Comment.Preproc: "noitalic", # class: 'cp' - Keyword: "bold #004461", # class: 'k' - Keyword.Constant: "bold #004461", # class: 'kc' - Keyword.Declaration: "bold #004461", # class: 'kd' - Keyword.Namespace: "bold #004461", # class: 'kn' - Keyword.Pseudo: "bold #004461", # class: 'kp' - Keyword.Reserved: "bold #004461", # class: 'kr' - Keyword.Type: "bold #004461", # class: 'kt' - Operator: "#582800", # class: 'o' - Operator.Word: "bold #004461", # class: 'ow' - like keywords - Punctuation: "bold #000000", # class: 'p' - # because special names such as Name.Class, Name.Function, etc. - # are not recognized as such later in the parsing, we choose them - # to look the same as ordinary variables. - Name: "#000000", # class: 'n' - Name.Attribute: "#c4a000", # class: 'na' - to be revised - Name.Builtin: "#004461", # class: 'nb' - Name.Builtin.Pseudo: "#3465a4", # class: 'bp' - Name.Class: "#000000", # class: 'nc' - to be revised - Name.Constant: "#000000", # class: 'no' - to be revised - Name.Decorator: "#888", # class: 'nd' - to be revised - Name.Entity: "#ce5c00", # class: 'ni' - Name.Exception: "bold #cc0000", # class: 'ne' - Name.Function: "#000000", # class: 'nf' - Name.Property: "#000000", # class: 'py' - Name.Label: "#f57900", # class: 'nl' - Name.Namespace: "#000000", # class: 'nn' - to be revised - Name.Other: "#000000", # class: 'nx' - Name.Tag: "bold #004461", # class: 'nt' - like a keyword - Name.Variable: "#000000", # class: 'nv' - to be revised - Name.Variable.Class: "#000000", # class: 'vc' - to be revised - Name.Variable.Global: "#000000", # class: 'vg' - to be revised - Name.Variable.Instance: "#000000", # class: 'vi' - to be revised - Number: "#990000", # class: 'm' - Literal: "#000000", # class: 'l' - Literal.Date: "#000000", # class: 'ld' - String: "#4e9a06", # class: 's' - String.Backtick: "#4e9a06", # class: 'sb' - String.Char: "#4e9a06", # class: 'sc' - String.Doc: "italic #8f5902", # class: 'sd' - like a comment - String.Double: "#4e9a06", # class: 's2' - String.Escape: "#4e9a06", # class: 'se' - String.Heredoc: "#4e9a06", # class: 'sh' - String.Interpol: "#4e9a06", # class: 'si' - String.Other: "#4e9a06", # class: 'sx' - String.Regex: "#4e9a06", # class: 'sr' - String.Single: "#4e9a06", # class: 's1' - String.Symbol: "#4e9a06", # class: 'ss' - Generic: "#000000", # class: 'g' - Generic.Deleted: "#a40000", # class: 'gd' - Generic.Emph: "italic #000000", # class: 'ge' - Generic.Error: "#ef2929", # class: 'gr' - Generic.Heading: "bold #000080", # class: 'gh' - Generic.Inserted: "#00A000", # class: 'gi' - Generic.Output: "#888", # class: 'go' - Generic.Prompt: "#745334", # class: 'gp' - Generic.Strong: "bold #000000", # class: 'gs' - Generic.Subheading: "bold #800080", # class: 'gu' - Generic.Traceback: "bold #a40000", # class: 'gt' - } diff --git a/docs/_themes/kr/autotoc.html b/docs/_themes/kr/autotoc.html deleted file mode 100644 index 2c12261..0000000 --- a/docs/_themes/kr/autotoc.html +++ /dev/null @@ -1,25 +0,0 @@ -

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

- - - - - - diff --git a/docs/_themes/kr/layout.html b/docs/_themes/kr/layout.html deleted file mode 100755 index 087a852..0000000 --- a/docs/_themes/kr/layout.html +++ /dev/null @@ -1,29 +0,0 @@ -{%- extends "basic/layout.html" %} -{%- block extrahead %} - {{ super() }} - - {% if theme_touch_icon %} - - {% endif %} - -{% endblock %} - - -{% block sidebar2 %} - {{ sidebar() }} -{% endblock %} - -{%- block footer %} - -
- -
- - Fork me on GitHub - - -{%- endblock %} diff --git a/docs/_themes/kr/relations.html b/docs/_themes/kr/relations.html deleted file mode 100755 index 3bbcde8..0000000 --- a/docs/_themes/kr/relations.html +++ /dev/null @@ -1,19 +0,0 @@ -

Related Topics

- diff --git a/docs/_themes/kr/sidebarlogo.html b/docs/_themes/kr/sidebarlogo.html deleted file mode 100644 index 0c24425..0000000 --- a/docs/_themes/kr/sidebarlogo.html +++ /dev/null @@ -1,15 +0,0 @@ -dataset - -

Because managing databases in Python should be as simple as reading and writing JSON files.

- - - -

Overview

- - - - diff --git a/docs/_themes/kr/static/flasky.css_t b/docs/_themes/kr/static/flasky.css_t deleted file mode 100755 index 9879049..0000000 --- a/docs/_themes/kr/static/flasky.css_t +++ /dev/null @@ -1,559 +0,0 @@ -/* - * flasky.css_t - * ~~~~~~~~~~~~ - * - * :copyright: Copyright 2010 by Armin Ronacher. Modifications by Kenneth Reitz. - * :license: Flask Design License, see LICENSE for details. - */ - -{% set page_width = '940px' %} -{% set sidebar_width = '220px' %} - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: "Georgia", "Open Sans", OpenSansRegular, sans-serif; - font-size: 16px; - background: #fff; - font-weight: 400; - color: #000; - margin: 0; - padding: 0; -} - -div.document { - width: {{ page_width }}; - margin: 30px auto 0 auto; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 {{ sidebar_width }}; -} - -div.sphinxsidebar { - width: {{ sidebar_width }}; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.body { - background-color: white; - color: #3E4349; - padding: 0 30px 0 30px; -} - -img.floatingflask { - padding: 0 0 10px 10px; - float: right; -} - -div.footer { - width: {{ page_width }}; - margin: 20px auto 30px auto; - font-size: 14px; - color: #888; - text-align: right; -} - -div.footer a { - color: #888; -} - -div.related { - display: none; -} - -div.sphinxsidebar a { - color: #444; - text-decoration: none; - border-bottom: 1px dotted #999; -} - -div.sphinxsidebar a:hover { - border-bottom: 1px solid #999; -} - -div.sphinxsidebar { - font-size: 14px; - line-height: 1.5; -} - -div.sphinxsidebarwrapper { - padding: 18px 10px; -} - -div.sphinxsidebarwrapper p.logo { - padding: 0; - margin: -10px 0 0 -20px; - text-align: center; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: 'Antic Slab' ,'Garamond', 'Georgia', serif; - color: #000; - font-size: 24px; - font-weight: normal; - margin: 30px 0 5px 0; - padding: 0; -} - -div.sphinxsidebar h4 { - font-size: 20px; -} - -div.sphinxsidebar h3 a { - color: #000; -} - -div.sphinxsidebar p.logo a, -div.sphinxsidebar h3 a, -div.sphinxsidebar p.logo a:hover, -div.sphinxsidebar h3 a:hover { - border: none; -} - -div.sphinxsidebar p { - color: #555; - margin: 10px 0; -} - -div.sphinxsidebar ul { - margin: 10px 0px; - padding: 0; - color: #000; -} - -div.sphinxsidebar input { - border: 1px solid #ccc; - font-family: 'Georgia', serif; - font-size: 1em; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #004B6B; - text-decoration: underline; -} - -a:hover { - color: #6D4100; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Antic Slab', serif; - font-weight: normal; - margin: 30px 0px 10px 0px; - padding: 0; - text-shadow: 1px 1px 3px #ddd; - color: #000; -} - -div.body h1 { margin-top: 0; padding-top: 0; font-size: 250%; } -div.body h2 { font-size: 190%; } -div.body h3 { font-size: 160%; } -div.body h4 { font-size: 140%; } -div.body h5 { font-size: 110%; } -div.body h6 { font-size: 110%; } - -a.headerlink { - color: #ddd; - padding: 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - color: #444; - background: #eaeaea; -} - -div.body p, div.body dd, div.body li { - line-height: 1.4em; -} - -div.admonition { - background: #fafafa; - margin: 20px -30px; - padding: 10px 30px; - border-top: 1px solid #ccc; - border-bottom: 1px solid #ccc; -} - -div.admonition tt.xref, div.admonition a tt { - border-bottom: 1px solid #fafafa; -} - -dd div.admonition { - margin-left: -60px; - padding-left: 60px; -} - -div.admonition p.admonition-title { - font-family: 'Garamond', 'Georgia', serif; - font-weight: normal; - font-size: 24px; - margin: 0 0 10px 0; - padding: 0; - line-height: 1; -} - -div.admonition p.last { - margin-bottom: 0; -} - -div.highlight { - background-color: white; -} - -dt:target, .highlight { - background: #FAF3E8; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.88em; -} - -tt { - font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; - font-size: 0.95em; -} - -img.screenshot { -} - -tt.descname, tt.descclassname { - font-size: 0.95em; -} - -tt.descname { - padding-right: 0.08em; -} - -img.screenshot { - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils { - border: 1px solid #888; - -moz-box-shadow: 2px 2px 4px #eee; - -webkit-box-shadow: 2px 2px 4px #eee; - box-shadow: 2px 2px 4px #eee; -} - -table.docutils td, table.docutils th { - border: 1px solid #888; - padding: 0.25em 0.7em; -} - -table.field-list, table.footnote { - border: none; - -moz-box-shadow: none; - -webkit-box-shadow: none; - box-shadow: none; -} - -table.footnote { - margin: 15px 0; - width: 100%; - border: 1px solid #eee; - background: #fdfdfd; - font-size: 0.9em; -} - -table.footnote + table.footnote { - margin-top: -15px; - border-top: none; -} - -table.field-list th { - padding: 0 0.8em 0 0; -} - -table.field-list td { - padding: 0; -} - -table.footnote td.label { - width: 0px; - padding: 0.3em 0 0.3em 0.5em; -} - -table.footnote td { - padding: 0.3em 0.5em; -} - -dl { - margin: 0; - padding: 0; -} - -dl dd { - margin-left: 30px; -} - -blockquote { - margin: 0 0 0 30px; - padding: 0; -} - -ul, ol { - margin: 10px 0 10px 30px; - padding: 0; -} - -pre { - background: #eee; - padding: 7px 30px; - margin: 15px -30px; - line-height: 1.3em; -} - -dl pre, blockquote pre, li pre { - margin-left: 0px; - padding-left: 15px; -} - -dl dl pre { - margin-left: 0px; - padding-left: 15px; -} - -tt { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ -} - -tt.xref, a tt { - background-color: #FBFBFB; - color: #2277bb; - border-bottom: 1px solid white; -} - -a.reference { - text-decoration: none; - border-bottom: 1px dotted #004B6B; -} - -a.reference:hover { - border-bottom: 1px solid #6D4100; -} - -a.footnote-reference { - text-decoration: none; - font-size: 0.7em; - vertical-align: top; - border-bottom: 1px dotted #004B6B; -} - -a.footnote-reference:hover { - border-bottom: 1px solid #6D4100; -} - -a:hover tt { - background: #EEE; -} - -li { - margin-bottom: 0.3em; -} - - -@media screen and (max-width: 870px) { - - div.sphinxsidebar { - display: none; - } - - div.document { - width: 100%; - - } - - div.documentwrapper { - margin-left: 0; - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - } - - div.bodywrapper { - margin-top: 0; - margin-right: 0; - margin-bottom: 0; - margin-left: 0; - } - - ul { - margin-left: 0; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .bodywrapper { - margin: 0; - } - - .footer { - width: auto; - } - - .github { - display: none; - } - - - -} - - - -@media screen and (max-width: 875px) { - - body { - margin: 0; - padding: 20px 30px; - } - - div.documentwrapper { - float: none; - background: white; - } - - div.sphinxsidebar { - display: block; - float: none; - width: 102.5%; - margin: 50px -30px -20px -30px; - padding: 10px 20px; - background: #333; - color: white; - } - - div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, - div.sphinxsidebar h3 a { - color: white; - } - - div.sphinxsidebar a { - color: #aaa; - } - - div.sphinxsidebar p.logo { - display: none; - } - - div.document { - width: 100%; - margin: 0; - } - - div.related { - display: block; - margin: 0; - padding: 10px 0 20px 0; - } - - div.related ul, - div.related ul li { - margin: 0; - padding: 0; - } - - div.footer { - display: none; - } - - div.bodywrapper { - margin: 0; - } - - div.body { - min-height: 0; - padding: 0; - } - - - .rtd_doc_footer { - display: none; - } - - .document { - width: auto; - } - - .footer { - width: auto; - } - - .footer { - width: auto; - } - - .github { - display: none; - } -} - - -/* misc. */ - -.revsys-inline { - display: none!important; -} - -div.sphinxsidebar #searchbox input[type="text"] { - width: 140px; - padding: 4px 3px; -} - -.highlight .nv { - color: #C65D09!important; -} diff --git a/docs/_themes/kr/theme.conf b/docs/_themes/kr/theme.conf deleted file mode 100755 index 07698f6..0000000 --- a/docs/_themes/kr/theme.conf +++ /dev/null @@ -1,7 +0,0 @@ -[theme] -inherit = basic -stylesheet = flasky.css -pygments_style = flask_theme_support.FlaskyStyle - -[options] -touch_icon = diff --git a/docs/api.rst b/docs/api.rst index 1986ed6..477f0bc 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -33,11 +33,7 @@ Table Data Export ----------- - **Note:** Data exporting has been extracted into a stand-alone package, datafreeze. See the relevant repository here_. .. _here: https://github.com/pudo/datafreeze -| - -.. autofunction:: datafreeze.freeze diff --git a/docs/conf.py b/docs/conf.py index 870f582..87fcb53 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,16 +41,16 @@ master_doc = "index" # General information about the project. project = u"dataset" -copyright = u"2013-2018, Friedrich Lindenberg, Gregor Aisch, Stefan Wehrmeyer" +copyright = u"2013-2021, Friedrich Lindenberg, Gregor Aisch, Stefan Wehrmeyer" # 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 = "1.0" +version = "1.4.2" # The full version, including alpha/beta/rc tags. -release = "1.0.8" +release = "1.4.2" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -94,175 +94,17 @@ pygments_style = "sphinx" # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = "kr" +html_theme = "furo" -# 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 = { -# 'stickysidebar': "true" -# } - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ["_themes"] - -# 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 = { - "index": ["sidebarlogo.html", "sourcelink.html", "searchbox.html"], - "api": ["sidebarlogo.html", "autotoc.html", "sourcelink.html", "searchbox.html"], - "**": ["sidebarlogo.html", "localtoc.html", "sourcelink.html", "searchbox.html"], +html_theme_options = { + "light_logo": "dataset-logo-light.png", + "dark_logo": "dataset-logo-dark.png", } -# 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_domain_indices = 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 = False -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = 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 = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = "datasetdoc" - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ( - "index", - "dataset.tex", - u"dataset Documentation", - u"Friedrich Lindenberg, Gregor Aisch, Stefan Wehrmeyer", - "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 - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ( - "index", - "dataset", - u"dataset Documentation", - [u"Friedrich Lindenberg, Gregor Aisch, Stefan Wehrmeyer"], - 1, - ) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - "index", - "dataset", - u"dataset Documentation", - u"Friedrich Lindenberg, Gregor Aisch, Stefan Wehrmeyer", - "dataset", - "Databases for lazy people.", - "Miscellaneous", - ), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False diff --git a/docs/index.rst b/docs/index.rst index 59990ce..1a72b0f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -62,6 +62,7 @@ Contents install quickstart api + queries Contributors ------------ diff --git a/docs/queries.rst b/docs/queries.rst new file mode 100644 index 0000000..86d26ff --- /dev/null +++ b/docs/queries.rst @@ -0,0 +1,53 @@ + +.. _advanced_filters: + +Advanced filters +================ + +``dataset`` provides two methods for running queries: :py:meth:`table.find() ` +and :py:meth:`db.query() `. The table find helper method provides +limited, but simple filtering options:: + + results = table.find((column, operator, value)) + # e.g.: + results = table.find(('name', 'like', '%mole rat%')) + +A special form is using keyword searches on specific columns:: + + results = table.find(value=5) + # equal to: + results = table.find((value, '=', 5)) + +The following comparison operators are supported: + +============== ============================================================ +Operator Description +============== ============================================================ +gt, > Greater than +lt, < Less than +gte, >= Greater or equal +lte, <= Less or equal +!=, <>, not Not equal to a single value +in Value is in the given sequence +like, ilike Text search, ILIKE is case-insensitive. Use ``%`` as a wildcard +between, .. Value is between two values in the given tuple +startswith String starts with +endswith String ends with +============== ============================================================ + +Querying for a specific value on a column that does not exist on the table +will return no results. + +Queries using raw SQL +--------------------- + +To run more complex queries with JOINs, or to perform GROUP BY-style +aggregation, you can also use :py:meth:`db.query() ` +to run raw SQL queries instead. This also supports paramterisation to avoid +SQL injections. + +Finally, you should consider falling back to SQLAlchemy_ core to construct +queries if you are looking for a programmatic, composable method of generating +SQL in Python. + +.. _SQLALchemy: https://docs.sqlalchemy.org/ \ No newline at end of file diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 1a9b676..359e8a0 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -142,20 +142,13 @@ We can search for specific entries using :py:meth:`find() ` winners = table.find(id=[1, 3, 7]) # Find by comparison operator - elderly_users = table.find(age={'>=': 70}) - possible_customers = table.find(age={'between': [21, 80]}) + elderly_users = table.find((age, '>=', 70)) + possible_customers = table.find((age, 'between', [21, 80])) # Use the underlying SQLAlchemy directly elderly_users = table.find(table.table.columns.age >= 70) -Possible comparison operators:: - - gt, > - lt, < - gte, >= - lte, <= - !=, <>, not - between, .. +See :ref:`advanced_filters` for details on complex filters. Using :py:meth:`distinct() ` we can grab a set of rows with unique values in one or more columns:: @@ -192,3 +185,30 @@ programmatic construction of more complex queries:: table = db['user'].table statement = table.select(table.c.name.like('%John%')) result = db.query(statement) + +Limitations of dataset +---------------------- + +The goal of ``dataset`` is to make basic database operations simpler, by expressing +some relatively basic operations in a Pythonic way. The downside of this approach +is that as your application grows more complex, you may begin to need access to +more advanced operations and be forced to switch to using SQLAlchemy proper, +without the dataset layer (instead, you may want to play with SQLAlchemy's ORM). + +When that moment comes, take the hit. SQLAlchemy is an amazing piece of Python +code, and it will provide you with idiomatic access to all of SQL's functions. + +Some of the specific aspects of SQL that are not exposed in ``dataset``, and are +considered out of scope for the project, include: + +* Foreign key relationships between tables, and expressing one-to-many and + many-to-many relationships in idiomatic Python. +* Python-wrapped ``JOIN`` queries. +* Creating databases, or managing DBMS software. +* Support for Python 2.x + +There's also some functionality that might be cool to support in the future, but +that requires signficant engineering: + +* Async operations +* Database-native ``UPSERT`` semantics diff --git a/docs/requirements.txt b/docs/requirements.txt index 04d359a..9e279e7 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1 @@ -datafreeze +furo \ No newline at end of file