diff --git a/.travis.yml b/.travis.yml index 6625cb8..830a5de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +# use http://lint.travis-ci.org/ to check the file. + language: python sudo: required @@ -8,6 +10,10 @@ cache: directories: - $HOME/miniconda +env: + global: + - secure:` "yxu/J/VNed5R6Fs1D5YJZ9hN3bMFAOBxFOkVyoxSfzTsDWeJ0rNLMljn7TTFeBBFpNI6PG3RFIzeOd3AAbtZKr4dQ/aL70woQ2nF7lNDbofudE+bdc/K0fKhS4dZZeMKyeRI3LItQgGJ1vSOYDGfpq0EhOd17d1oo9pqjDli+pTzjJ6qvDQ41e5mmRPVXIqJ2mLpnf+jZdvHJTzog0d4kS+BQOqhLYe1AATyYyHFrs95kroAVkLbuPhQ0KVQX3h8NV3OD+x+qQjmM2Zl6mygoABh8jbkAv2/Kx/WcBR/rLO6WG2z+ZBwdP/2R7/Gh0Tac9An+Kvf8L1GCdyeMoS55XlUTwyqbpOQydASs8PlGnQuNFk3QaeJcjWJgFJjoYUDC8yQt/avkjkiPPa6kraUQalEYD66t5dKrL2UICCUUJ4lXkHGD532tLOFS2dJTRRgUQD/d8q4cNzdNY9X4LaHYDJxhFWi+sV/gOYrSSc1uF4pxlpU8naBR/eaJHN1+eGb5h76LC1uF7zcjYLFmsP+YmMVwyVKU3bbcPmHNsoDgrtAY0bF4gDVLDeqmZzt4OLz9ATtHNRST9yEjmiyjUXX9O+kXYFGOd14XMw+S0vdqwSPeobavFTaUmz0+AUQiPkJf0FpLbHmUHfY/0m3PvlwQYFyskgYzjjhNtR362fCtgg=" + # Removing the directory will remove the env but leave the cached packages # at $HOME/miniconda/pkgs. That is a win-win because when re-creating the # env we will download only the new packages. @@ -48,6 +54,8 @@ matrix: env: TEST_TARGET=default - python: 2.7 env: TEST_TARGET=coding_standards + - python: 3.6 + env: TEST_TARGET=docs allow_failures: - python: 2.7 env: TEST_TARGET=coding_standards @@ -72,6 +80,7 @@ before_install: - export PATH="$HOME/miniconda/bin:$PATH" - conda config --set always_yes yes --set changeps1 no --set show_channel_urls true - conda update conda + - conda config --add channels conda-forge --force - conda config --add channels odm2 --force - conda create --name TEST python=$TRAVIS_PYTHON_VERSION --file requirements.txt --file requirements-dev.txt - source activate TEST @@ -89,3 +98,17 @@ script: - if [[ $TEST_TARGET == 'coding_standards' ]]; then find . -type f -name "*.py" ! -name 'conf.py' | xargs flake8 --max-line-length=100 ; fi + + - if [[ $TEST_TARGET == 'docs' ]]; then + set -e ; + conda install doctr ; + pushd docs ; + make clean html linkcheck ; + popd ; + python -m doctr deploy --sync .; + python -m doctr deploy --sync --no-require-master --built-docs docs/build/html "docs-$TRAVIS_BRANCH" ; + fi + +doctr: + require-master: true + sync: False diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..e421db0 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = python -msphinx +SPHINXPROJ = ODM2PythonAPI +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/doc/APIFunctionList.md b/docs/_NOTES/APIFunctionList.md similarity index 100% rename from doc/APIFunctionList.md rename to docs/_NOTES/APIFunctionList.md diff --git a/doc/DatabaseNotes.md b/docs/_NOTES/DatabaseNotes.md similarity index 100% rename from doc/DatabaseNotes.md rename to docs/_NOTES/DatabaseNotes.md diff --git a/doc/MySql.md b/docs/_NOTES/MySql.md similarity index 100% rename from doc/MySql.md rename to docs/_NOTES/MySql.md diff --git a/doc/distribution_notes.txt b/docs/_NOTES/distribution_notes.txt similarity index 100% rename from doc/distribution_notes.txt rename to docs/_NOTES/distribution_notes.txt diff --git a/doc/notes_sqlacodegen.txt b/docs/_NOTES/notes_sqlacodegen.txt similarity index 100% rename from doc/notes_sqlacodegen.txt rename to docs/_NOTES/notes_sqlacodegen.txt diff --git a/doc/wxFormBuilder/dbConfigurationPnl.fbp b/docs/_NOTES/wxFormBuilder/dbConfigurationPnl.fbp similarity index 100% rename from doc/wxFormBuilder/dbConfigurationPnl.fbp rename to docs/_NOTES/wxFormBuilder/dbConfigurationPnl.fbp diff --git a/docs/source/_static/logo.png b/docs/source/_static/logo.png new file mode 100644 index 0000000..ce53b6d Binary files /dev/null and b/docs/source/_static/logo.png differ diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..80574df --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,177 @@ +# -*- coding: utf-8 -*- +# +# ODM2PythonAPI documentation build configuration file, created by +# sphinx-quickstart on Thu Sep 28 11:03:57 2017. +# +# 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. + +# 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. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# 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.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'ODM2PythonAPI' +copyright = u'2017, Stephanie Reeder' +author = u'Stephanie Reeder' + +# 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. + +from odm2api._version import get_versions +version = release = get_versions()['version'] +del get_versions + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# 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 = { + 'logo': 'logo.png', + 'logo_name': 'ODM2', + 'github_user': 'ODM2', + 'github_repo': 'ODM2PythonAPI', + 'github_banner': True, + 'travis_button': True, + 'fixed_sidebar': True, +} + +# 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'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# This is required for the alabaster theme +# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars +html_sidebars = { + '**': [ + 'about.html', + 'navigation.html', + 'relations.html', # needs 'show_related': True theme option to display + 'searchbox.html', + 'donate.html', + ] +} + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'ODM2PythonAPIdoc' + + +# -- 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': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'ODM2PythonAPI.tex', u'ODM2PythonAPI Documentation', + u'Stephanie Reeder', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'odm2pythonapi', u'ODM2PythonAPI Documentation', + [author], 1) +] + + +# -- 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 = [ + (master_doc, 'ODM2PythonAPI', u'ODM2PythonAPI Documentation', + author, 'ODM2PythonAPI', 'One line description of project.', + 'Miscellaneous'), +] diff --git a/docs/source/credits.rst b/docs/source/credits.rst new file mode 100644 index 0000000..9ba5d88 --- /dev/null +++ b/docs/source/credits.rst @@ -0,0 +1,10 @@ +Credits +------- + +This work was supported by National Science Foundation Grants +`EAR-1224638 `__ +and +`ACI-1339834 `__. +Any opinions, findings, and conclusions or recommendations expressed in +this material are those of the author(s) and do not necessarily reflect +the views of the National Science Foundation. diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..554e7ae --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,19 @@ +ODM2 Python API +=============== + +A Python-based application programmer's interface for the `Observations Data Model 2 (ODM2) `__. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + installing + modules + credits + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/installing.rst b/docs/source/installing.rst new file mode 100644 index 0000000..dc9b164 --- /dev/null +++ b/docs/source/installing.rst @@ -0,0 +1,62 @@ +Installation +------------ + +The easiest and most reliable way to install the ODM2 Python API +(``odm2api``) is using the `Conda package management +system `__ via either +`Anaconda `__ or +`Miniconda `__. To start using +conda (if it's not your system default), add conda to the PATH; on +OS X and Linux, it's something like +``export PATH=$HOME/miniconda3/bin:$PATH``, but the exact path may vary. + +To activate a conda environment, say, "myenv": + +.. code:: bash + + activate myenv # On Windows + source activate myenv # On MacOSX or Linux + +**Note:** ``odm2api`` currently is only tested on Python 2.7. Some +changes have been made to support Python 3.x, but they haven't been +tested thoroughly. + +Latest release, from ODM2 anaconda.org channel +---------------------------------------------- + +The `latest release `__ is available +on the `ODM2 anaconda.org channel `__ +for all major OS platforms (linux, OS X, win32/win64). To install it on +an existing conda environment: + +:: + + conda install odm2api --channel odm2 + +All dependencies are installed, including Pandas and its dependencies +(numpy, etc). + +To create a new environment "myenv" with the ``odm2api`` package: + +:: + + conda create -n myenv -c odm2 python=2.7 odm2api + + +Installing the development version +---------------------------------- + +To create a new environment "myenv" with ``odm2api``, first clone the repository. +Then, on a terminal shell: + +.. code:: bash + + conda create --name myenv python=2.7 --file requirements.txt --file requirements-dev.txt -c odm2 + +Activate the new environment, then install ``odm2api`` into the +environment: + +.. code:: bash + + activate myenv # On Windows + source activate myenv # On OS X or Linux diff --git a/docs/source/modules.rst b/docs/source/modules.rst new file mode 100644 index 0000000..9f4fe1b --- /dev/null +++ b/docs/source/modules.rst @@ -0,0 +1,7 @@ +:mod:`ODMconnection` +--------------------- + +.. automodule:: odm2api.ODMconnection + :members: + :undoc-members: + :show-inheritance: diff --git a/github_deploy_key.enc b/github_deploy_key.enc new file mode 100644 index 0000000..73ce4ef --- /dev/null +++ b/github_deploy_key.enc @@ -0,0 +1 @@ +gAAAAABZzR8jV8tLA-UYXPm9LOmRhSt9G3CH9z04Zu1RqllofDhvfqVeLJzc14API4ebFXyxV40utk-4vYE-613lUhdGk9ZMotUUszBfnzmXMKAJL0iu-59SgIM8jTMJR09IutvRzmO6bL9y3LOFvbfMBL9aXRqPag36SJzQqn5v8p9wefZGoGZTrP_0n2Umt_qFrh6HCFQD3SBzoPyXHj2V8C07qjHQAFt9myH_JJpgET0vz3S0DOvHjCqDYFBtWw5B3JS7ymg8xdnD7Yq7q-gnQn6-FO4IYrCQna_CN0FjE8AA3lnaxaSiD3D_vsl_5Pyq0qb2AXZLk7QH3dULFGTgheVEmpumVjDsjX2N8dgY2r6e6YWDxeEvNNjtUaoJHweiEBEHgVPUvdEZlU-MQHBom3jYr-mijNU8AHLpKs4ybHSykl5EA0RyV3yZ0KsDxWKoi8U6OalHZOuUJmlwtAsQKMslxhQP-h2Fdw9MVuAnzugpZxFr2uR99pivkeybyWiRXaKTcFb2C4-d1Y9I9sFgOPtiImIFwpyt0vYLd5md-RusBKXLAmxVS8YK28SMEPxsJ6Bs9BYumgo3-sOr2PfUJKAzTrEl47XEevrMd_GuqI-Cj7RmhlKWh70BRbnHxUDxy1kO8AJOsCbFUgAT_yz_5LbwIXkk8f1HQAAMUo1ZeiyVr9Ju5f8MRel0K7wmHP3AnG-TS4AmrSq88ItZr5dy7gsFDjTKe_g7KRo75xo7mI9IgJSzs3LE7e-cHr57-gMzsfCgW8d61mT8gR3IXjcuSKEaozJEZBsk-EJbiKAEldPFkYUJC41tpv_64M7gXLAzxcRCf3Dx2WAd0j3QFuFn0gZhSCckaDG0jemQVnPbJtzChgocpHWqjFkB_akP5qtq8XSmPaWhVf7Jq-AKU3PjC17FF0_BNgBj8aJ7ACQswQhnV_D-qqswDX4QZgQ0C58_jXGR4oyDVo0NkiG7JYMsp7lHyXoomRyG1l3D0Etyspac8EZ43m5Jnn90AN2OZ4qNHDzjDeGzYZP3nZuitqwVxk82VmCJZu7LCgykWp7hGMIMEJDV1zjWZoQ15YziBbZWUxEjpP6RjijiQmIC9J8yX9HLrrFImimzc-FAOaNd8D8KM_Sn7_u7xvfegJwMgvR0PsrXnUc_YEfR5lBqQTv03AzzQorH5FbSfOooUhq64gzm3YCDUZislM0Z3G6Poc_bbWPzHDQTCaFub8NPR55JtI4FhIr9eBBGsDomrE9nEAn2yYjDV6I0whwcCigieK8axiyA9O0KZT0buyhbWrfXoUAvo8-lWoydNM013aFLI-ZD9pKazauTeTamS5NQoXOdgOKXLzP3E409qlyFZdrz4bUDV2l-0CYX6r6WmnfeapwyIiTEOLy1wK-ccizdWuq8oGgDnjIfU0Fw7-hFNU0Q8-FtMd9Pn841qZh3Tnr3yZQNYWP0lX9ibqY4L1R59kI61ss4RkK4N0uZcVa0j8awvoMaN9UPqzJS36z0ibvjLgZEChTgK0vXAKy9qAQra20R5UBMKqcgFLRHv4V0KluL9Ml480_km2UGXj1xlOBCq5rQ00iceUTKkkjLbkjRAfOH8LPq1DmNGrz4W-LZgd7q6I_y6zWkCPsaXVUelv_Hogz14kpXm5Ox_HhlwPtfBeLv6Jk0fjhj3I3YCg9KiLDIXuzj8P3Wd76pIK4YB4l0D6M8pHfPX2x1-55tPSoj88Bk43S8Wgv_gQhxtqcAQt8SJaroacN3m5hGlEpIqQNQOHgj9emdGekmPJSN6UXXHXOqCWOo6wAp9DFpiUyo-gox1Gu3YMU10yt17ZDVTbB8G6xZ-VKDinsjVlmM92OasLJth3ec3acrz_c-QeFg1bBQwuciMRqGrbJr5CoHOxWXiF7GVrzh0borwzNhl6YQrBYR7lykRVksOCpOT69eKse75KUUdBqgH4kNoQoFpa32P53s1wEfKfBq3ZrSIRIREn6CpliYtF8ugcrO7bS1v7V-UQRFEGlfowzOqiTKqPHFeO2TJWcqCBiTmkOQz6T5yrUSdWLqo9aNl1mSJxQ27ouqF8AIplwLeNofFIJcvbj_3bJfPNXemLtpk2EUFATr39XKStjoBhMwuSTZg1xmhFKSFmg5z4O250xntOPruJIZ8-y8FdMeV-5RMpD_wdAm4PdWHXbRM_9fZ36ma7NsuKfI2-l_8dS5YJ3QxxFYGZAKhiIx8khKA_f_eo4WvjVulTJdMmdW5bI8c6HyNoZv3tbiIFILr-9vEmWzM2ujidpU35a42ONlKpgLeQzrqdi_z5M6l6NpqmJ1E29bskxX5nihbd3tjJY4NUQTugwTpOyzYMqDULtK0yo9fSLUuDDdK3clKvmIHsghqAMNH9Ya6j1SnZNE5Qy9-R9qkf2fUDlal8CrcIcVze1GAXTnXum1FdKyl7BHkrgm3V9vsEEyhdzj4ldp4Ibz6RLZ2pqXSIhB9XSHYm63ur6kwKcNHvZCNooLXsfz43h8GVcVJrsFOFNFfp1MU0VrB9H2xcGemUm1DfroZK0Ymv6rAvAbbOtxN9ZtDiAAVaI-1ZpW_stxS__hIr_PI7m6wP0Fc64zBfJPonUiCke2bZt9nJNNM0hmDsAzXIoooPVWgdAVGKDG8TDF2Oa0RSYyJ9yt6OJ5wH5GncHTOw4wEnAQhWZee4w65fufNuSNy-nQpn4G2zoM4TkN8m6BVKCUoef3xY2ByJVk50SgEvR5xC2F93BNXFoBzVryFxHY4luuJAnx4nf7AEevKiGefBJyHPAGFfckYOr4_nT2F01aJ1O02tavP0AMyZSiFaBMb1MKfNY99hQhlUdIS68bI2KP7l6QQiFrh0u1U3Mj0WKBeqKWGH3Uy5_QRQeXfcat53GMULB9iGkG0UHsHT4VkQWIA8fuk160IZtolpAiTAMsTXEt31l61AlJIV3XXsf4BhdUKSsj8usENpRDosQx56q1sqFbGl80KQwToYiZzig3iTLhszUUor9BEYDmvhpswAh5jWTppzuSg5xDTmpELVniy9_95MA70iaakbKOgztgT90qJdMJFDpAkl_qzYWJmbamYmZUUf93ZgwzAohPYT865dab_2u9HNJTA4r9Fq1R86keptr3Cm3Gb3lZ4vD1HifwiEhBwzvdhyD7VWJAaxl9ekE0w68keKtkbK5HIrN5lhEe5nk_fVzXvcd5SE6pSqw5XtXYz2NKaubcJ0VBLkcgOwq-MY95cirbm_ocM99VhZIi2E74s-zxb8sJleMH4z1Ioe06ss_s9bN1xZuLvzEkY53sDYCBzihXBmoBsSWdFdz-pZ5puqU4TH4Yz-nmR0jbAp2FHimVxCP4sgNMJsXLlaVJwcSkMBZH0ZP4zE_gbRmev9t-JrbGeUPTzrHlP4pQYs-AwRNdgojllZhI6R2RqvhRFkZgpOZPgJbrHO6yHAT8pPGBRSLkPIsNGAHFjz0uCAk_LJsLqvNnGjthJJPhFHp6WOgyFAU8dN06JzPELVW6o5LEg-EJW022uS4B7txzEcHp90iwC6Wjyts8RDVgUX9o0tjnvmh78le_XDo8mYOS2uMAuZBbk988SRgWZDIECNJV_4SaUZgDkJPk3sb-KaQ_E924KL-tjiqGyiEq7ylvyQp6hgmylfLeAf8z4hTVPSJ0y4ibJ_ZlUpSUgnbwTAo0JhOGna0EwRF7F-CbsMDggFRfNsNvyzzCfhPiYoh6BPn9uxusPt1yofstqpcNep4MGbuoj28rPK5BMu7jP2id1lBT252NGI2spSWcAa4kdBlAoQXFj1czr8MeEhj2HkjLYGbupTaYLo-C0XXabmp4mhTh3TQ0uJxnz6RkrXPqZ1jD9CtnMVcavuubGag__CC1-6t0_wmIgm3-PJG1Zs8km47lgxqXynEzebAUbUm9Rs6mq5GpDRzFfAtLi6cf3OY4nEHdHoJzSZv-sd_XMkx2JDxnWsUtjgCCsnAaYEgVbdZ0wT_qy9V0pDC7nZhPacR8Zce3diIw3bjUagtT2P_SzLCVMt8KYJY983Y04OKuV75p59QGa4Tcd7BphKJ68AUtKR1sjsEJx2ktgaPfQI0UC7MmhEe9qdF8_KB7PNTKKZxhMfStciGKmjZb1Zrmw2wunmuNGgDLISAWpGjQ-2OWePfQYi_Wdn-ful4q6G7agrdwwMD3kM5a8QTBdaoXOYa_ZvHY51ek1JEI-5PpBA8KJAhnHgm84GCa7QKnKXYgZXmiRwOF_jHHlLjNvDUW5SgAeB9KaLa7wC-A8PZ-ybXiq9EAbcFKVeav1WAMFC3MhJW3pfKHOC4tp6pfaCPMqQoWA-8Z6lUyBwcBVyTsCVZLxXCWKqcD3srDxac8JCqqepjRt8u89V_FS4s01eSjN4yad56q51amAax0zrUpaZ0= \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt index 122ec9e..71bb791 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,9 +1,19 @@ +alabaster flake8 +flake8-builtins +flake8-comprehensions +flake8-import-order +flake8-mutable +flake8-print +flake8-quotes mock +nbsphinx psycopg2 +pycodestyle pymysql pytest pytest-cov +sphinx # FIXME: I am not sure these are needed. # pysqlite # sqlite