mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Merge branch 'doc'
This commit is contained in:
commit
2af1d5f428
12 changed files with 1287 additions and 18 deletions
146
doc/Makefile
Normal file
146
doc/Makefile
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
# Makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER =
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||||
|
|
||||||
|
all: doctest
|
||||||
|
$(MAKE) html coverage
|
||||||
|
|
||||||
|
commit:
|
||||||
|
mkdir -p _gh-pages
|
||||||
|
(cd _gh-pages && git init || true)
|
||||||
|
rm -rf _build/html/.git
|
||||||
|
cp -r _gh-pages/.git _build/html
|
||||||
|
(cd _build/html && git add . && git commit -m "sphinx build $$(date --rfc-3339=seconds)" || true)
|
||||||
|
(cd _gh-pages && git pull ../_build/html)
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@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 " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@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 $(BUILDDIR)/*
|
||||||
|
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
touch $(BUILDDIR)/html/.nojekyll
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
|
dirhtml:
|
||||||
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pokedex.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pokedex.qhc"
|
||||||
|
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/pokedex"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pokedex"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
make -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||||
|
cat $(BUILDDIR)/coverage/*.txt
|
230
doc/conf.py
Normal file
230
doc/conf.py
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# pokedex documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Tue Apr 12 17:43:05 2011.
|
||||||
|
#
|
||||||
|
# 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 sys, os
|
||||||
|
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding("UTF-8")
|
||||||
|
|
||||||
|
# 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.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.doctest',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.pngmath',
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
#'sphinx.ext.viewcode',
|
||||||
|
'sphinx.ext.coverage',
|
||||||
|
'pokedex.doc.tabledoc',
|
||||||
|
]
|
||||||
|
|
||||||
|
# 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'pokedex'
|
||||||
|
copyright = u'2011, Alex Munroe (Eevee)'
|
||||||
|
|
||||||
|
# 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 = '0.1'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = '0.1'
|
||||||
|
|
||||||
|
# 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 patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
|
# 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 = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
|
intersphinx_mapping = {'sqlalchemy': ('http://www.sqlalchemy.org/docs', None)}
|
||||||
|
|
||||||
|
# -- 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 = 'default'
|
||||||
|
|
||||||
|
# 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 = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> 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_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 = True
|
||||||
|
|
||||||
|
# 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 = False
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> 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 = 'pokedexdoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- 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', 'pokedex.tex', u'Pokedex Documentation',
|
||||||
|
u'veekun', '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
|
||||||
|
|
||||||
|
# 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_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', 'pokedex', u'Pokedex Documentation',
|
||||||
|
[u'veekun'], 1)
|
||||||
|
]
|
25
doc/index.rst
Normal file
25
doc/index.rst
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
.. pokedex documentation master file, created by
|
||||||
|
sphinx-quickstart on Tue Apr 12 17:43:05 2011.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
The pokedex documentation
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Jump right in!
|
||||||
|
|
||||||
|
Contents:
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installing
|
||||||
|
usage
|
||||||
|
schema
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
156
doc/installing.rst
Normal file
156
doc/installing.rst
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
Installing the pokedex library
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Quick startup with Ubuntu/Debian-like systems
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
Run the following from an empty directory::
|
||||||
|
|
||||||
|
$ sudo apt-get install git python python-pip python-sqlalchemy
|
||||||
|
$ git clone git://github.com/veekun/pokedex.git
|
||||||
|
$ pip install -E env -e pokedex
|
||||||
|
$ source env/bin/activate
|
||||||
|
(env)$ pokedex setup -v
|
||||||
|
(env)$ pokedex lookup eevee
|
||||||
|
|
||||||
|
If it all goes smoothly, you can now use ``env/bin/pokedex``, the command-line
|
||||||
|
tool, and ``env/bin/python``, a Python interpreter configured to use the
|
||||||
|
pokedex library.
|
||||||
|
|
||||||
|
That is all you need. Feel free to skip the rest of this chapter if you're not
|
||||||
|
interested in the details.
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Linux
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
Ubuntu/Debian users should run the following::
|
||||||
|
|
||||||
|
$ sudo apt-get install git python python-pip
|
||||||
|
|
||||||
|
With other Linuxes, install the packages for git, python (2.6 or 2.7,
|
||||||
|
*not* 3.x), and python-pip.
|
||||||
|
|
||||||
|
If you succeeded, skip the Detailed instructions.
|
||||||
|
|
||||||
|
Detailed instructions
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You should know what a command line is and how to work with it.
|
||||||
|
The here we assume you're using Linux [#]_, if that's not the case, make
|
||||||
|
sure you have enough computer knowledge to translate the instructions to your
|
||||||
|
operating system.
|
||||||
|
|
||||||
|
Pokedex is distributed via Git_. So, get Git.
|
||||||
|
|
||||||
|
You will also need Python_ 2; the language pokedex is written in. Be sure to get
|
||||||
|
version **2.6** or **2.7**. Pokedex does not work with Python 3.x yet, and it
|
||||||
|
most likely won't work with 2.5 or earlier.
|
||||||
|
|
||||||
|
Next, get pip_, a tool to install Python packages. Experts can use another
|
||||||
|
tool, of course.
|
||||||
|
|
||||||
|
Make sure git and pip are on your path.
|
||||||
|
|
||||||
|
Optionally you can install SQLAlchemy_, `Python markdown`_, Whoosh_,
|
||||||
|
or construct_. If you don't, pip will atuomatically download and install a copy
|
||||||
|
for you, but some are pretty big so you might want to install it system-wide.
|
||||||
|
(Unfortunately, many distros have outdated versions of these libraries, so pip
|
||||||
|
will install pokedex's own copy anyway.)
|
||||||
|
|
||||||
|
Getting and installing pokedex
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Run the following from an empty directory::
|
||||||
|
|
||||||
|
$ git clone git://git.veekun.com/pokedex.git
|
||||||
|
$ pip install -E env -e pokedex
|
||||||
|
|
||||||
|
This will give you two directories: pokedex (containing the source code and
|
||||||
|
data), and env (a virtualenv_).
|
||||||
|
|
||||||
|
In env/bin, there are three interesting files:
|
||||||
|
|
||||||
|
* pokedex: The pokedex program
|
||||||
|
* python: A copy of Python that knows about pokedex and its prerequisites.
|
||||||
|
* activate: Typing ``source env/bin/activate`` in a shell will put
|
||||||
|
pokedex and our bin/python on the $PATH, and generally set things up to work
|
||||||
|
with them. Your prompt will change to let you know of this. You can end such
|
||||||
|
a session by typing ``deactivate``.
|
||||||
|
|
||||||
|
This documentation will assume that you've activated the virtualenv, so
|
||||||
|
``pokedex`` means ``env/bin/pokedex``.
|
||||||
|
|
||||||
|
Advanced
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
You can of course install into an existing virtualenv, by either using its pip
|
||||||
|
and leaving out the ``-E env``, or running the setup script directly::
|
||||||
|
|
||||||
|
(anotherenv)$ cd pokedex
|
||||||
|
(anotherenv)pokedex$ python setup.py develop
|
||||||
|
|
||||||
|
It is also possible to install pokedex system-wide. There are problems with
|
||||||
|
that. Don't do it. The only time you need ``sudo`` is for getting the
|
||||||
|
prerequisites.
|
||||||
|
|
||||||
|
Loading the database
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Before you can do anything useful with pokedex, you need to load the database::
|
||||||
|
|
||||||
|
$ pokedex setup -v
|
||||||
|
|
||||||
|
This will load the data into a default SQLite database and create a default
|
||||||
|
Whoosh index.
|
||||||
|
|
||||||
|
Advanced
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
If you want to use another database, make sure you have the corresponding
|
||||||
|
`SQLAlchemy engine`_ for it and either use the ``-e`` switch, (e.g.
|
||||||
|
``-e postgresql://@/pokedex``), or set the ``POKEDEX_DB_ENGINE`` environment
|
||||||
|
variable.
|
||||||
|
|
||||||
|
To use another lookup index directory, specify it with ``-i`` or the
|
||||||
|
``POKEDEX_INDEX_DIR`` variable.
|
||||||
|
|
||||||
|
Make sure you always use the same options whenever you use pokedex.
|
||||||
|
|
||||||
|
If you're confused about what pokedex thinks its settings are, check
|
||||||
|
``pokedex status``.
|
||||||
|
|
||||||
|
See ``pokedex help`` for even more options.
|
||||||
|
|
||||||
|
All done
|
||||||
|
--------
|
||||||
|
|
||||||
|
To verify that all went smoothly, check that the pokedex tool finds your
|
||||||
|
favorite pokémon::
|
||||||
|
|
||||||
|
$ pokedex lookup eevee
|
||||||
|
|
||||||
|
Yes, that was a bit anti-climatic. The command-line tool doesn't do much,
|
||||||
|
currently.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _Git: http://git-scm.com/
|
||||||
|
.. _Python: http://www.python.org/
|
||||||
|
.. _pip: http://pypi.python.org/pypi/pip
|
||||||
|
.. _SQLAlchemy: www.sqlalchemy.org/
|
||||||
|
.. _`Python markdown`: http://www.freewisdom.org/projects/python-markdown/
|
||||||
|
.. _Whoosh: http://whoosh.ca/
|
||||||
|
.. _construct: pypi.python.org/pypi/construct
|
||||||
|
.. _virtualenv: http://www.virtualenv.org/en/latest/
|
||||||
|
.. _`SQLAlchemy engine`: http://www.sqlalchemy.org/docs/core/engines.html
|
||||||
|
|
||||||
|
.. rubric:: Footnotes
|
||||||
|
.. [#] If you write instructions for another OS, well be happy to include them
|
||||||
|
here. The reason your OS is not listed here is because the author doesn't
|
||||||
|
use it, so naturally he can't write instructions for it.
|
179
doc/main-tables.rst
Normal file
179
doc/main-tables.rst
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
The pokédex tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. module:: pokedex.db.tables
|
||||||
|
|
||||||
|
The :mod:`pokedex.db.tables` module defines all of the tables in the Pokédex.
|
||||||
|
They are all defined with SQLAlchemy's
|
||||||
|
:mod:`~sqlalchemy.ext.declarative` extension.
|
||||||
|
|
||||||
|
To introspect the tables programmatically, you can use the following:
|
||||||
|
|
||||||
|
.. data:: mapped_classes
|
||||||
|
|
||||||
|
A list of all the classes you see below.
|
||||||
|
|
||||||
|
.. data:: metadata
|
||||||
|
|
||||||
|
The SQLAlchemy :class:`~sqlalchemy.schema.MetaData` containing all the
|
||||||
|
tables.
|
||||||
|
|
||||||
|
Each of the classes has a ``translation_classes`` attribute: a potentially
|
||||||
|
empty list of translation classes. See :mod:`pokedex.db.multilang` for how
|
||||||
|
these work.
|
||||||
|
|
||||||
|
Many tables have these columns:
|
||||||
|
|
||||||
|
- **id**: An integer primary key. Sometimes it's semantically meaningful, most
|
||||||
|
often it isn't.
|
||||||
|
- **identifier**: A string identifier of the class, and the preferred way to
|
||||||
|
access individual items.
|
||||||
|
- **name**: A name (uses the multilang functionality)
|
||||||
|
|
||||||
|
Pokémon
|
||||||
|
-------
|
||||||
|
|
||||||
|
.. dex-table:: PokemonSpecies
|
||||||
|
.. dex-table:: Pokemon
|
||||||
|
.. dex-table:: PokemonForm
|
||||||
|
.. dex-table:: EvolutionChain
|
||||||
|
.. dex-table:: PokemonEvolution
|
||||||
|
|
||||||
|
Moves
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. dex-table:: Move
|
||||||
|
.. dex-table:: MoveEffect
|
||||||
|
.. dex-table:: MoveMeta
|
||||||
|
|
||||||
|
Items
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. dex-table:: Item
|
||||||
|
.. dex-table:: Berry
|
||||||
|
|
||||||
|
Types
|
||||||
|
-----
|
||||||
|
|
||||||
|
.. dex-table:: Type
|
||||||
|
|
||||||
|
Abilities
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. dex-table:: Ability
|
||||||
|
|
||||||
|
Language
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. dex-table:: Language
|
||||||
|
|
||||||
|
Version stuff
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. dex-table:: Generation
|
||||||
|
.. dex-table:: VersionGroup
|
||||||
|
.. dex-table:: Version
|
||||||
|
.. dex-table:: Pokedex
|
||||||
|
.. dex-table:: Region
|
||||||
|
|
||||||
|
Encounters
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. dex-table:: Location
|
||||||
|
.. dex-table:: LocationArea
|
||||||
|
.. dex-table:: LocationAreaEncounterRate
|
||||||
|
.. dex-table:: Encounter
|
||||||
|
.. dex-table:: EncounterCondition
|
||||||
|
.. dex-table:: EncounterConditionValue
|
||||||
|
.. dex-table:: EncounterMethod
|
||||||
|
.. dex-table:: EncounterSlot
|
||||||
|
|
||||||
|
|
||||||
|
Contests
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. dex-table:: ContestCombo
|
||||||
|
.. dex-table:: ContestEffect
|
||||||
|
.. dex-table:: SuperContestCombo
|
||||||
|
.. dex-table:: SuperContestEffect
|
||||||
|
|
||||||
|
Enum tables
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. dex-table:: BerryFirmness
|
||||||
|
.. dex-table:: ContestType
|
||||||
|
.. dex-table:: EggGroup
|
||||||
|
.. dex-table:: EvolutionTrigger
|
||||||
|
.. dex-table:: GrowthRate
|
||||||
|
.. dex-table:: ItemCategory
|
||||||
|
.. dex-table:: ItemFlingEffect
|
||||||
|
.. dex-table:: ItemPocket
|
||||||
|
.. dex-table:: MoveBattleStyle
|
||||||
|
.. dex-table:: MoveDamageClass
|
||||||
|
.. dex-table:: MoveMetaAilment
|
||||||
|
.. dex-table:: MoveMetaCategory
|
||||||
|
.. dex-table:: MoveTarget
|
||||||
|
.. dex-table:: Nature
|
||||||
|
.. dex-table:: PalParkArea
|
||||||
|
.. dex-table:: PokemonColor
|
||||||
|
.. dex-table:: PokemonMoveMethod
|
||||||
|
.. dex-table:: PokemonShape
|
||||||
|
.. dex-table:: Stat
|
||||||
|
|
||||||
|
Changelogs
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. dex-table:: AbilityChangelog
|
||||||
|
.. dex-table:: MoveEffectChangelog
|
||||||
|
.. dex-table:: MoveChangelog
|
||||||
|
|
||||||
|
Flavor text
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. dex-table:: ItemFlavorText
|
||||||
|
.. dex-table:: AbilityFlavorText
|
||||||
|
.. dex-table:: MoveFlavorText
|
||||||
|
.. dex-table:: PokemonSpeciesFlavorText
|
||||||
|
|
||||||
|
Association tables
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. dex-table:: BerryFlavor
|
||||||
|
.. dex-table:: EncounterConditionValueMap
|
||||||
|
.. dex-table:: ItemFlag
|
||||||
|
.. dex-table:: ItemFlagMap
|
||||||
|
.. dex-table:: Machine
|
||||||
|
.. dex-table:: MoveFlag
|
||||||
|
.. dex-table:: MoveFlagMap
|
||||||
|
.. dex-table:: MoveMetaStatChange
|
||||||
|
.. dex-table:: NatureBattleStylePreference
|
||||||
|
.. dex-table:: NaturePokeathlonStat
|
||||||
|
.. dex-table:: PokeathlonStat
|
||||||
|
.. dex-table:: PokemonAbility
|
||||||
|
.. dex-table:: PokemonEggGroup
|
||||||
|
.. dex-table:: PokemonFormPokeathlonStat
|
||||||
|
.. dex-table:: PokemonHabitat
|
||||||
|
.. dex-table:: PokemonMove
|
||||||
|
.. dex-table:: PokemonStat
|
||||||
|
.. dex-table:: PokemonItem
|
||||||
|
.. dex-table:: PokemonType
|
||||||
|
.. dex-table:: TypeEfficacy
|
||||||
|
.. dex-table:: VersionGroupPokemonMoveMethod
|
||||||
|
.. dex-table:: VersionGroupRegion
|
||||||
|
|
||||||
|
Index maps
|
||||||
|
----------
|
||||||
|
|
||||||
|
.. dex-table:: ItemGameIndex
|
||||||
|
.. dex-table:: LocationGameIndex
|
||||||
|
.. dex-table:: PokemonDexNumber
|
||||||
|
.. dex-table:: PokemonFormGeneration
|
||||||
|
.. dex-table:: PokemonGameIndex
|
||||||
|
|
||||||
|
Mics tables
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. dex-table:: Experience
|
||||||
|
.. dex-table:: PalPark
|
||||||
|
.. dex-table:: StatHint
|
||||||
|
|
6
doc/schema.rst
Normal file
6
doc/schema.rst
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
The database schema
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
|
||||||
|
main-tables
|
193
doc/usage.rst
Normal file
193
doc/usage.rst
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
Using pokedex
|
||||||
|
=============
|
||||||
|
|
||||||
|
The pokédex is, first and foremost, a Python library. To get the most of it,
|
||||||
|
you'll need to learn `Python`_ and `SQLAlchemy`_.
|
||||||
|
|
||||||
|
Here is a small example of using pokedex:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
from pokedex.db import connect, tables, util
|
||||||
|
session = connect()
|
||||||
|
pokemon = util.get(session, tables.PokemonSpecies, 'bulbasaur')
|
||||||
|
print u'{0.name}, the {0.genus} Pokemon'.format(pokemon)
|
||||||
|
|
||||||
|
Running this will give you some Bulbasaur info:
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
Bulbasaur, the Seed Pokemon
|
||||||
|
|
||||||
|
Connecting
|
||||||
|
----------
|
||||||
|
|
||||||
|
To get information out of the Pokédex, you will need to create a
|
||||||
|
:class:`Session <pokedex.db.multilang.MultilangSession>`. To do that, use
|
||||||
|
:func:`pokedex.db.connect`. For simple uses, you don't need to give it any
|
||||||
|
arguments: it the database that ``pokedex load`` fills up by default. If you
|
||||||
|
need to select another database, give its URI as the first argument.
|
||||||
|
|
||||||
|
The object :func:`~pokedex.db.connect` gives you is actually a
|
||||||
|
:class:`SQLAlchemy session <sqlalchemy.orm.session.Session>`, giving you the
|
||||||
|
full power of SQLAlchemy for working with the data. We'll cover some basics
|
||||||
|
here, but if you intend to do some serious work, do read SQLAlchemy's docs.
|
||||||
|
|
||||||
|
Pokédex tables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Data in the pokédex is organized in tables, defined in
|
||||||
|
:mod:`pokedex.db.tables`.
|
||||||
|
There is quite a few or them. To get you started, here are a few common ones:
|
||||||
|
|
||||||
|
* :class:`~pokedex.db.tables.PokemonSpecies`
|
||||||
|
* :class:`~pokedex.db.tables.Move`
|
||||||
|
* :class:`~pokedex.db.tables.Item`
|
||||||
|
* :class:`~pokedex.db.tables.Type`
|
||||||
|
|
||||||
|
Getting things
|
||||||
|
--------------
|
||||||
|
|
||||||
|
If you know what you want from the pokédex, you can use the
|
||||||
|
:func:`pokedex.db.util.get` function. It looks up a thing in a table, based on
|
||||||
|
its identifier, name, or ID, and returns it.
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
def print_pokemon(pokemon):
|
||||||
|
print u'{0.name}, the {0.genus} Pokemon'.format(pokemon)
|
||||||
|
|
||||||
|
print_pokemon(util.get(session, tables.PokemonSpecies, identifier='eevee'))
|
||||||
|
print_pokemon(util.get(session, tables.PokemonSpecies, name=u'Ho-Oh'))
|
||||||
|
print_pokemon(util.get(session, tables.PokemonSpecies, id=50))
|
||||||
|
|
||||||
|
def print_item(item):
|
||||||
|
print u'{0.name}: ${0.cost}'.format(item)
|
||||||
|
|
||||||
|
print_item(util.get(session, tables.Item, identifier='great-ball'))
|
||||||
|
print_item(util.get(session, tables.Item, name='Potion'))
|
||||||
|
print_item(util.get(session, tables.Item, id=30))
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
Eevee, the Evolution Pokemon
|
||||||
|
Ho-Oh, the Rainbow Pokemon
|
||||||
|
Diglett, the Mole Pokemon
|
||||||
|
Great Ball: $600
|
||||||
|
Potion: $300
|
||||||
|
Fresh Water: $200
|
||||||
|
|
||||||
|
Querying
|
||||||
|
--------
|
||||||
|
|
||||||
|
So, how do you get data from the session? You use the session's
|
||||||
|
:meth:`~sqlalchemy.orm.session.Session.query` method, and give it a pokédex
|
||||||
|
Table as an argument. This will give you a :class:`SQLAlchemy query
|
||||||
|
<sqlalchemy.orm.query.Query>`.
|
||||||
|
|
||||||
|
Ordering
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
As always with SQL, you should not rely on query results being in some
|
||||||
|
particular order – unless you have ordered the query first. This means that
|
||||||
|
you'll want to sort just about every query you will make.
|
||||||
|
|
||||||
|
For example, you can get a list of all pokémon species, sorted by their
|
||||||
|
:attr:`~pokedex.db.tables.PokemonSpecies.id`, like so:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
for pokemon in session.query(tables.PokemonSpecies).order_by(tables.PokemonSpecies.id):
|
||||||
|
print pokemon.name
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
Bulbasaur
|
||||||
|
Ivysaur
|
||||||
|
Venusaur
|
||||||
|
Charmander
|
||||||
|
Charmeleon
|
||||||
|
...
|
||||||
|
Keldeo
|
||||||
|
Meloetta
|
||||||
|
Genesect
|
||||||
|
|
||||||
|
Or to order by :attr:`~pokedex.db.tables.PokemonSpecies.name`:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
for pokemon in session.query(tables.PokemonSpecies).order_by(tables.PokemonSpecies.name):
|
||||||
|
print pokemon.name
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
Abomasnow
|
||||||
|
...
|
||||||
|
Zweilous
|
||||||
|
|
||||||
|
|
||||||
|
Filtering
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
Another major operation on queries is filtering, using the query's
|
||||||
|
:meth:`~sqlalchemy.orm.query.Query.filter` or
|
||||||
|
:meth:`~sqlalchemy.orm.query.Query.filter_by` methods:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
for move in session.query(tables.Move).filter(tables.Move.power > 200):
|
||||||
|
print move.name
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
Explosion
|
||||||
|
|
||||||
|
Joining
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
The final operation we'll cover here is joining other tables to the query,
|
||||||
|
using the query's :meth:`~sqlalchemy.orm.query.Query.join`.
|
||||||
|
You will usually want to join on a relationship, such as in the following
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. testcode::
|
||||||
|
|
||||||
|
query = session.query(tables.Move)
|
||||||
|
query = query.join(tables.Move.type)
|
||||||
|
query = query.filter(tables.Type.identifier == 'grass')
|
||||||
|
query = query.filter(tables.Move.power >= 100)
|
||||||
|
query = query.order_by(tables.Move.power)
|
||||||
|
query = query.order_by(tables.Move.name)
|
||||||
|
|
||||||
|
print 'The most powerful Grass-type moves:'
|
||||||
|
for move in query:
|
||||||
|
print u'{0.name} ({0.power})'.format(move)
|
||||||
|
|
||||||
|
.. testoutput::
|
||||||
|
|
||||||
|
The most powerful Grass-type moves:
|
||||||
|
Petal Dance (120)
|
||||||
|
Power Whip (120)
|
||||||
|
Seed Flare (120)
|
||||||
|
SolarBeam (120)
|
||||||
|
Wood Hammer (120)
|
||||||
|
Leaf Storm (140)
|
||||||
|
Frenzy Plant (150)
|
||||||
|
|
||||||
|
That concludes our brief tutorial.
|
||||||
|
If you need to do more, consult the `SQLAlchemy documentation`_.
|
||||||
|
|
||||||
|
API documentation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. autofunction:: pokedex.db.connect
|
||||||
|
|
||||||
|
See :class:`sqlalchemy.orm.session.Session` for more documentation on the
|
||||||
|
returned object.
|
||||||
|
|
||||||
|
.. autofunction:: pokedex.db.util.get
|
||||||
|
|
||||||
|
|
||||||
|
.. _Python: http://www.python.org
|
||||||
|
.. _SQLAlchemy: http://www.sqlalchemy.org
|
||||||
|
.. _`SQLAlchemy documentation`: http://www.sqlalchemy.org/docs/orm/tutorial.html
|
|
@ -118,6 +118,7 @@ def create_translation_table(_table_name, foreign_class, relation_name,
|
||||||
|
|
||||||
Translations = type(_table_name, (object,), {
|
Translations = type(_table_name, (object,), {
|
||||||
'_language_identifier': association_proxy('local_language', 'identifier'),
|
'_language_identifier': association_proxy('local_language', 'identifier'),
|
||||||
|
'relation_name': relation_name,
|
||||||
})
|
})
|
||||||
|
|
||||||
# Create the table object
|
# Create the table object
|
||||||
|
|
|
@ -1272,6 +1272,7 @@ class PokemonForm(TableBase):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
"""Name of this form: the form_name, if set; otherwise the species name"""
|
||||||
return self.pokemon_name or self.species.name
|
return self.pokemon_name or self.species.name
|
||||||
|
|
||||||
create_translation_table('pokemon_form_names', PokemonForm, 'names',
|
create_translation_table('pokemon_form_names', PokemonForm, 'names',
|
||||||
|
@ -1705,7 +1706,6 @@ ContestCombo.second = relationship(Move,
|
||||||
innerjoin=True, lazy='joined',
|
innerjoin=True, lazy='joined',
|
||||||
backref='contest_combo_second')
|
backref='contest_combo_second')
|
||||||
|
|
||||||
|
|
||||||
Encounter.condition_value_map = relationship(EncounterConditionValueMap,
|
Encounter.condition_value_map = relationship(EncounterConditionValueMap,
|
||||||
backref='encounter')
|
backref='encounter')
|
||||||
Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
|
Encounter.condition_values = association_proxy('condition_value_map', 'condition_value')
|
||||||
|
@ -1954,10 +1954,8 @@ Pokemon.all_abilities = relationship(Ability,
|
||||||
secondary=PokemonAbility.__table__,
|
secondary=PokemonAbility.__table__,
|
||||||
order_by=PokemonAbility.slot.asc(),
|
order_by=PokemonAbility.slot.asc(),
|
||||||
innerjoin=True,
|
innerjoin=True,
|
||||||
backref=backref('all_pokemon',
|
backref=backref('all_pokemon', order_by=Pokemon.order.asc()),
|
||||||
order_by=Pokemon.order.asc(),
|
doc=u"All abilities the Pokémon can have, including the Hidden Ability")
|
||||||
),
|
|
||||||
)
|
|
||||||
Pokemon.abilities = relationship(Ability,
|
Pokemon.abilities = relationship(Ability,
|
||||||
secondary=PokemonAbility.__table__,
|
secondary=PokemonAbility.__table__,
|
||||||
primaryjoin=and_(
|
primaryjoin=and_(
|
||||||
|
@ -1966,10 +1964,8 @@ Pokemon.abilities = relationship(Ability,
|
||||||
),
|
),
|
||||||
innerjoin=True,
|
innerjoin=True,
|
||||||
order_by=PokemonAbility.slot.asc(),
|
order_by=PokemonAbility.slot.asc(),
|
||||||
backref=backref('pokemon',
|
backref=backref('pokemon', order_by=Pokemon.order.asc()),
|
||||||
order_by=Pokemon.order.asc(),
|
doc=u"Abilities the Pokémon can have in the wild")
|
||||||
),
|
|
||||||
)
|
|
||||||
Pokemon.dream_ability = relationship(Ability,
|
Pokemon.dream_ability = relationship(Ability,
|
||||||
secondary=PokemonAbility.__table__,
|
secondary=PokemonAbility.__table__,
|
||||||
primaryjoin=and_(
|
primaryjoin=and_(
|
||||||
|
@ -1977,10 +1973,8 @@ Pokemon.dream_ability = relationship(Ability,
|
||||||
PokemonAbility.is_dream == True,
|
PokemonAbility.is_dream == True,
|
||||||
),
|
),
|
||||||
uselist=False,
|
uselist=False,
|
||||||
backref=backref('dream_pokemon',
|
backref=backref('dream_pokemon', order_by=Pokemon.order),
|
||||||
order_by=Pokemon.order,
|
doc=u"The Pokémon's Hidden Ability")
|
||||||
),
|
|
||||||
)
|
|
||||||
Pokemon.forms = relationship(PokemonForm,
|
Pokemon.forms = relationship(PokemonForm,
|
||||||
primaryjoin=Pokemon.id==PokemonForm.pokemon_id,
|
primaryjoin=Pokemon.id==PokemonForm.pokemon_id,
|
||||||
order_by=(PokemonForm.order.asc(), PokemonForm.form_identifier.asc()),
|
order_by=(PokemonForm.order.asc(), PokemonForm.form_identifier.asc()),
|
||||||
|
@ -1989,9 +1983,11 @@ Pokemon.default_form = relationship(PokemonForm,
|
||||||
primaryjoin=and_(
|
primaryjoin=and_(
|
||||||
Pokemon.id==PokemonForm.pokemon_id,
|
Pokemon.id==PokemonForm.pokemon_id,
|
||||||
PokemonForm.is_default==True),
|
PokemonForm.is_default==True),
|
||||||
uselist=False, lazy='joined')
|
uselist=False, lazy='joined',
|
||||||
|
doc=u"A representative form of this pokémon")
|
||||||
Pokemon.items = relationship(PokemonItem,
|
Pokemon.items = relationship(PokemonItem,
|
||||||
backref='pokemon')
|
backref='pokemon',
|
||||||
|
doc=u"Info about items this pokémon holds in the wild")
|
||||||
Pokemon.stats = relationship(PokemonStat,
|
Pokemon.stats = relationship(PokemonStat,
|
||||||
innerjoin=True,
|
innerjoin=True,
|
||||||
order_by=PokemonStat.stat_id.asc(),
|
order_by=PokemonStat.stat_id.asc(),
|
||||||
|
@ -2077,7 +2073,9 @@ PokemonStat.stat = relationship(Stat,
|
||||||
PokemonSpecies.parent_species = relationship(PokemonSpecies,
|
PokemonSpecies.parent_species = relationship(PokemonSpecies,
|
||||||
primaryjoin=PokemonSpecies.evolves_from_species_id==PokemonSpecies.id,
|
primaryjoin=PokemonSpecies.evolves_from_species_id==PokemonSpecies.id,
|
||||||
remote_side=[PokemonSpecies.id],
|
remote_side=[PokemonSpecies.id],
|
||||||
backref='child_species')
|
backref=backref('child_species',
|
||||||
|
doc=u"The species to which this one evolves"),
|
||||||
|
doc=u"The species from which this one evolves")
|
||||||
PokemonSpecies.evolutions = relationship(PokemonEvolution,
|
PokemonSpecies.evolutions = relationship(PokemonEvolution,
|
||||||
primaryjoin=PokemonSpecies.id==PokemonEvolution.evolved_species_id,
|
primaryjoin=PokemonSpecies.id==PokemonEvolution.evolved_species_id,
|
||||||
backref=backref('evolved_species', innerjoin=True, lazy='joined'))
|
backref=backref('evolved_species', innerjoin=True, lazy='joined'))
|
||||||
|
@ -2108,7 +2106,8 @@ PokemonSpecies.default_form = relationship(PokemonForm,
|
||||||
Pokemon.is_default==True),
|
Pokemon.is_default==True),
|
||||||
secondaryjoin=and_(Pokemon.id==PokemonForm.pokemon_id,
|
secondaryjoin=and_(Pokemon.id==PokemonForm.pokemon_id,
|
||||||
PokemonForm.is_default==True),
|
PokemonForm.is_default==True),
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
doc=u"A representative form of this species")
|
||||||
PokemonSpecies.default_pokemon = relationship(Pokemon,
|
PokemonSpecies.default_pokemon = relationship(Pokemon,
|
||||||
primaryjoin=and_(
|
primaryjoin=and_(
|
||||||
PokemonSpecies.id==Pokemon.species_id,
|
PokemonSpecies.id==Pokemon.species_id,
|
||||||
|
|
0
pokedex/doc/__init__.py
Normal file
0
pokedex/doc/__init__.py
Normal file
334
pokedex/doc/tabledoc.py
Normal file
334
pokedex/doc/tabledoc.py
Normal file
|
@ -0,0 +1,334 @@
|
||||||
|
# Encoding: UTF-8
|
||||||
|
|
||||||
|
u"""Automatic documentation generation for pokédex tables
|
||||||
|
|
||||||
|
This adds a "dex-table" directive to Sphinx, which works like "autoclass",
|
||||||
|
but documents Pokédex mapped classes.
|
||||||
|
"""
|
||||||
|
# XXX: This assumes all the tables are in pokedex.db.tables
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.statemachine import ViewList
|
||||||
|
from sphinx.util.compat import Directive, make_admonition
|
||||||
|
from sphinx.locale import _
|
||||||
|
from sphinx.domains.python import PyClasslike
|
||||||
|
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||||
|
from sphinx.ext.autodoc import ClassLevelDocumenter
|
||||||
|
|
||||||
|
from sqlalchemy import types
|
||||||
|
from sqlalchemy.orm.attributes import InstrumentedAttribute
|
||||||
|
from sqlalchemy.orm.properties import RelationshipProperty
|
||||||
|
from sqlalchemy.orm import Mapper, configure_mappers
|
||||||
|
from sqlalchemy.ext.associationproxy import AssociationProxy
|
||||||
|
from pokedex.db.markdown import MoveEffectPropertyMap, MoveEffectProperty
|
||||||
|
|
||||||
|
from pokedex.db import tables, markdown
|
||||||
|
|
||||||
|
# Make sure all the backrefs are in place
|
||||||
|
configure_mappers()
|
||||||
|
|
||||||
|
|
||||||
|
column_to_cls = {}
|
||||||
|
for cls in tables.mapped_classes:
|
||||||
|
for column in cls.__table__.c:
|
||||||
|
column_to_cls[column] = cls
|
||||||
|
|
||||||
|
class dextabledoc(nodes.Admonition, nodes.Element):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def visit_todo_node(self, node):
|
||||||
|
self.visit_admonition(node)
|
||||||
|
|
||||||
|
def depart_todo_node(self, node):
|
||||||
|
self.depart_admonition(node)
|
||||||
|
|
||||||
|
def column_type_str(column):
|
||||||
|
"""Extract the type name from a SQLA column
|
||||||
|
"""
|
||||||
|
type_ = column.type
|
||||||
|
# We're checking the specific type here: no issubclass
|
||||||
|
if type(type_) in (types.Integer, types.SmallInteger):
|
||||||
|
return 'int'
|
||||||
|
if type(type_) == types.Boolean:
|
||||||
|
return 'bool'
|
||||||
|
if type(type_) == types.Unicode:
|
||||||
|
return u'unicode – %s' % column.info['format']
|
||||||
|
if type(type_) == types.Enum:
|
||||||
|
return 'enum: [%s]' % ', '.join(type_.enums)
|
||||||
|
if type(type_) == markdown.MarkdownColumn:
|
||||||
|
return 'markdown'
|
||||||
|
raise ValueError(repr(type_))
|
||||||
|
|
||||||
|
common_columns = 'id identifier name'.split()
|
||||||
|
|
||||||
|
def column_header(c, class_name=None, transl_name=None, show_type=True,
|
||||||
|
relation=None, relation_name=None):
|
||||||
|
"""Return the column header for the given column"""
|
||||||
|
result = []
|
||||||
|
if relation_name:
|
||||||
|
name = relation_name
|
||||||
|
else:
|
||||||
|
name = c.name
|
||||||
|
if class_name:
|
||||||
|
result.append(u'%s.\ **%s**' % (class_name, name))
|
||||||
|
else:
|
||||||
|
result.append(u'**%s**' % c.name)
|
||||||
|
if c.foreign_keys:
|
||||||
|
for fk in c.foreign_keys:
|
||||||
|
if fk.column in column_to_cls:
|
||||||
|
foreign_cls = column_to_cls[fk.column]
|
||||||
|
if relation_name and relation_name + '_id' == c.name:
|
||||||
|
result.append(u'(%s →' % c.name)
|
||||||
|
elif relation_name:
|
||||||
|
result.append(u'(**%s** →' % c.name)
|
||||||
|
else:
|
||||||
|
result.append(u'(→')
|
||||||
|
result.append(u':class:`~pokedex.db.tables.%s`.%s)' % (
|
||||||
|
foreign_cls.__name__,
|
||||||
|
fk.column.name
|
||||||
|
))
|
||||||
|
break
|
||||||
|
elif show_type:
|
||||||
|
result.append(u'(*%s*)' % column_type_str(c))
|
||||||
|
if transl_name:
|
||||||
|
result.append(u'via *%s*' % transl_name)
|
||||||
|
return ' '.join(result)
|
||||||
|
|
||||||
|
|
||||||
|
def with_header(header=None):
|
||||||
|
"""Decorator that adds a section header if there's a any output
|
||||||
|
|
||||||
|
The decorated function should yield output lines; if there are any the
|
||||||
|
header gets added.
|
||||||
|
"""
|
||||||
|
def wrap(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapped(cls, remaining_attrs):
|
||||||
|
result = list(func(cls, remaining_attrs))
|
||||||
|
if result:
|
||||||
|
# Sphinx/ReST doesn't allow "-----" just anywhere :(
|
||||||
|
yield u''
|
||||||
|
yield u'.. raw:: html'
|
||||||
|
yield u''
|
||||||
|
yield u' <hr>'
|
||||||
|
yield u''
|
||||||
|
if header:
|
||||||
|
yield header + u':'
|
||||||
|
yield u''
|
||||||
|
for row in result:
|
||||||
|
yield row
|
||||||
|
return wrapped
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
### Section generation functions
|
||||||
|
|
||||||
|
def generate_table_header(cls, remaining_attrs):
|
||||||
|
first_line, sep, next_lines = unicode(cls.__doc__).partition(u'\n')
|
||||||
|
yield first_line
|
||||||
|
for line in textwrap.dedent(next_lines).split('\n'):
|
||||||
|
yield line
|
||||||
|
yield ''
|
||||||
|
|
||||||
|
yield u'Table name: *%s*' % cls.__tablename__
|
||||||
|
try:
|
||||||
|
yield u'(single: *%s*)' % cls.__singlename__
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
yield u''
|
||||||
|
|
||||||
|
yield u'Primary key: %s.' % u', '.join(
|
||||||
|
u'**%s**' % col.key for col in cls.__table__.primary_key.columns)
|
||||||
|
yield u''
|
||||||
|
|
||||||
|
def generate_common(cls, remaining_attrs):
|
||||||
|
common_col_headers = []
|
||||||
|
for c in cls.__table__.c:
|
||||||
|
if c.name in common_columns:
|
||||||
|
common_col_headers.append(column_header(c, show_type=False))
|
||||||
|
remaining_attrs.remove(c.name)
|
||||||
|
for translation_class in cls.translation_classes:
|
||||||
|
for c in translation_class.__table__.c:
|
||||||
|
if c.name in common_columns:
|
||||||
|
common_col_headers.append(column_header(c, None,
|
||||||
|
translation_class.__table__.name, show_type=False))
|
||||||
|
remaining_attrs.remove(c.name)
|
||||||
|
|
||||||
|
if common_col_headers:
|
||||||
|
if len(common_col_headers) > 1:
|
||||||
|
common_col_headers[-1] = 'and ' + common_col_headers[-1]
|
||||||
|
if len(common_col_headers) > 2:
|
||||||
|
separator = u', '
|
||||||
|
else:
|
||||||
|
separator = u' '
|
||||||
|
yield u'Has'
|
||||||
|
yield separator.join(common_col_headers) + '.'
|
||||||
|
yield u''
|
||||||
|
|
||||||
|
@with_header(u'Columns')
|
||||||
|
def generate_columns(cls, remaining_attrs):
|
||||||
|
name = cls.__name__
|
||||||
|
for c in [c for c in cls.__table__.c if c.name not in common_columns]:
|
||||||
|
remaining_attrs.remove(c.name)
|
||||||
|
relation_name = c.name[:-3]
|
||||||
|
if c.name.endswith('_id') and relation_name in remaining_attrs:
|
||||||
|
relation = getattr(cls, relation_name)
|
||||||
|
yield column_header(c, name,
|
||||||
|
relation=relation, relation_name=relation_name)
|
||||||
|
remaining_attrs.remove(relation_name)
|
||||||
|
else:
|
||||||
|
yield column_header(c, name) + ':'
|
||||||
|
yield u''
|
||||||
|
yield u' ' + unicode(c.info['description'])
|
||||||
|
yield u''
|
||||||
|
|
||||||
|
@with_header(u'Internationalized strings')
|
||||||
|
def generate_strings(cls, remaining_attrs):
|
||||||
|
for translation_class in cls.translation_classes:
|
||||||
|
for c in translation_class.__table__.c:
|
||||||
|
if 'format' in c.info:
|
||||||
|
remaining_attrs.discard(c.name)
|
||||||
|
remaining_attrs.discard(c.name + '_map')
|
||||||
|
if c.name in common_columns:
|
||||||
|
continue
|
||||||
|
yield column_header(c, cls.__name__,
|
||||||
|
translation_class.__table__.name)
|
||||||
|
yield u''
|
||||||
|
yield u' ' + unicode(c.info['description'])
|
||||||
|
yield u''
|
||||||
|
|
||||||
|
@with_header(u'Relationships')
|
||||||
|
def generate_relationships(cls, remaining_attrs):
|
||||||
|
def isrelationship(prop):
|
||||||
|
return isinstance(prop, InstrumentedAttribute) and isinstance(prop.property, RelationshipProperty)
|
||||||
|
|
||||||
|
for attr_name in sorted(remaining_attrs):
|
||||||
|
prop = getattr(cls, attr_name)
|
||||||
|
if not isrelationship(prop):
|
||||||
|
continue
|
||||||
|
rel = prop.property
|
||||||
|
yield u'%s.\ **%s**' % (cls.__name__, attr_name)
|
||||||
|
class_name = u':class:`~pokedex.db.tables.%s`' % rel.mapper.class_.__name__
|
||||||
|
if rel.uselist:
|
||||||
|
class_name = u'[%s]' % class_name
|
||||||
|
yield u'(→ %s)' % class_name
|
||||||
|
if rel.doc:
|
||||||
|
yield u''
|
||||||
|
yield u' ' + unicode(rel.doc)
|
||||||
|
if rel.secondary is not None:
|
||||||
|
yield u''
|
||||||
|
yield ' Association table: ``%s``' % rel.secondary
|
||||||
|
#if rel.primaryjoin is not None:
|
||||||
|
# yield u''
|
||||||
|
# yield ' Join condition: ``%s``' % rel.primaryjoin
|
||||||
|
# if rel.secondaryjoin is not None:
|
||||||
|
# yield ' , ``%s``' % rel.secondaryjoin
|
||||||
|
if rel.order_by:
|
||||||
|
yield u''
|
||||||
|
yield u' '
|
||||||
|
yield ' Ordered by: ' + u', '.join(
|
||||||
|
u'``%s``' % o for o in rel.order_by)
|
||||||
|
yield u''
|
||||||
|
remaining_attrs.remove(attr_name)
|
||||||
|
|
||||||
|
@with_header(u'Association Proxies')
|
||||||
|
def generate_associationproxies(cls, remaining_attrs):
|
||||||
|
for attr_name in sorted(remaining_attrs):
|
||||||
|
prop = getattr(cls, attr_name)
|
||||||
|
if isinstance(prop, AssociationProxy):
|
||||||
|
yield u'%s.\ **%s**:' % (cls.__name__, attr_name)
|
||||||
|
yield '``{prop.remote_attr.key}`` of ``self.{prop.local_attr.key}``'.format(
|
||||||
|
prop=prop)
|
||||||
|
'''if 'description' in info:
|
||||||
|
yield u''
|
||||||
|
yield u' ' + unicode(info['description'])'''
|
||||||
|
yield u''
|
||||||
|
remaining_attrs.remove(attr_name)
|
||||||
|
|
||||||
|
|
||||||
|
@with_header(u'Undocumented')
|
||||||
|
def generate_undocumented(cls, remaining_attrs):
|
||||||
|
for c in sorted([c for c in remaining_attrs if isinstance(getattr(cls, c),
|
||||||
|
(InstrumentedAttribute, AssociationProxy,
|
||||||
|
MoveEffectPropertyMap, MoveEffectProperty))]):
|
||||||
|
yield u''
|
||||||
|
yield u'%s.\ **%s**' % (cls.__name__, c)
|
||||||
|
remaining_attrs.remove(c)
|
||||||
|
|
||||||
|
@with_header(None)
|
||||||
|
def generate_other(cls, remaining_attrs):
|
||||||
|
for c in sorted(remaining_attrs):
|
||||||
|
yield u''
|
||||||
|
member = getattr(cls, c)
|
||||||
|
if callable(member):
|
||||||
|
yield '.. automethod:: %s.%s' % (cls.__name__, c)
|
||||||
|
else:
|
||||||
|
yield '.. autoattribute:: %s.%s' % (cls.__name__, c)
|
||||||
|
yield u''
|
||||||
|
remaining_attrs.clear()
|
||||||
|
|
||||||
|
|
||||||
|
class DexTable(PyClasslike):
|
||||||
|
"""The actual Sphinx documentation generation whatchamacallit
|
||||||
|
"""
|
||||||
|
doc_field_types = [
|
||||||
|
TypedField('field', label='Fields',
|
||||||
|
typerolename='obj', typenames=('fieldname', 'type')),
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_signature_prefix(self, sig):
|
||||||
|
return ''
|
||||||
|
#return u'mapped class '
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
section = nodes.section()
|
||||||
|
super_result = super(DexTable, self).run()
|
||||||
|
title_text = self.names[0][0]
|
||||||
|
section += nodes.title(text=title_text)
|
||||||
|
section += super_result
|
||||||
|
section['ids'] = ['dex-table-%s' % title_text.lower()]
|
||||||
|
return [section]
|
||||||
|
|
||||||
|
def before_content(self):
|
||||||
|
name = self.names[0][0]
|
||||||
|
for cls in tables.mapped_classes:
|
||||||
|
if name == cls.__name__:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise ValueError('Table %s not found' % name)
|
||||||
|
table = cls.__table__
|
||||||
|
|
||||||
|
remaining_attrs = set(x for x in dir(cls) if not x.startswith('_'))
|
||||||
|
remaining_attrs.difference_update(['metadata', 'translation_classes',
|
||||||
|
'add_relationships', 'summary_column'])
|
||||||
|
for transl_class in cls.translation_classes:
|
||||||
|
remaining_attrs.difference_update([
|
||||||
|
transl_class.relation_name,
|
||||||
|
transl_class.relation_name + '_table',
|
||||||
|
transl_class.relation_name + '_local',
|
||||||
|
])
|
||||||
|
|
||||||
|
generated_content = [] # Just a list of lines!
|
||||||
|
|
||||||
|
generated_content.extend(generate_table_header(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_common(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_columns(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_strings(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_relationships(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_associationproxies(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_undocumented(cls, remaining_attrs))
|
||||||
|
generated_content.extend(generate_other(cls, remaining_attrs))
|
||||||
|
|
||||||
|
generated_content.append(u'')
|
||||||
|
self.content = ViewList(generated_content + list(self.content))
|
||||||
|
return super(DexTable, self).before_content()
|
||||||
|
|
||||||
|
def get_index_text(self, modname, name_cls):
|
||||||
|
return '%s (mapped class)' % name_cls[0]
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_directive('dex-table', DexTable)
|
||||||
|
|
||||||
|
# XXX: Specify that this depends on pokedex.db.tables ...?
|
2
setup.py
2
setup.py
|
@ -8,7 +8,7 @@ setup(
|
||||||
'pokedex': ['data/csv/*.csv']
|
'pokedex': ['data/csv/*.csv']
|
||||||
},
|
},
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'SQLAlchemy>=0.7',
|
'SQLAlchemy>=0.7.3',
|
||||||
'whoosh>=2.2.2',
|
'whoosh>=2.2.2',
|
||||||
'markdown',
|
'markdown',
|
||||||
'construct',
|
'construct',
|
||||||
|
|
Loading…
Reference in a new issue