First version of integrated Graphene sphinx docs

This commit is contained in:
Syrus Akbary 2016-09-11 21:47:34 -07:00
parent a2140110c2
commit a0d07343e1
15 changed files with 1342 additions and 0 deletions

225
docs/Makefile Normal file
View File

@ -0,0 +1,225 @@
# 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) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help
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 " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " epub3 to make an epub3"
@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 " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
@echo " dummy to check syntax errors of document sources"
.PHONY: clean
clean:
rm -rf $(BUILDDIR)/*
.PHONY: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
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."
.PHONY: qthelp
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/Graphene.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Graphene.qhc"
.PHONY: applehelp
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Graphene"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Graphene"
@echo "# devhelp"
.PHONY: epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: epub3
epub3:
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
@echo
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
.PHONY: latex
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)."
.PHONY: latexpdf
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."
.PHONY: latexpdfja
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
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."
.PHONY: doctest
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
.PHONY: dummy
dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."

434
docs/conf.py Normal file
View File

@ -0,0 +1,434 @@
# -*- coding: utf-8 -*-
#
# Graphene documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 11 18:30:51 2016.
#
# 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.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
'sphinx.ext.githubpages',
]
# 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 encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Graphene'
copyright = u'Graphene 2016'
author = u'Syrus Akbary'
# 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 = u'1.0'
# The full version, including alpha/beta/rc tags.
release = u'1.0.dev'
# 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
# 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.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# 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 = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- 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 = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'Graphene v1.0.dev'
# 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 (relative to this directory) to use as a 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']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# 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 = True
# 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
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'Graphenedoc'
# -- 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, 'Graphene.tex', u'Graphene Documentation',
u'Syrus Akbary', '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 = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# 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 = [
(master_doc, 'graphene', u'Graphene Documentation',
[author], 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 = [
(master_doc, 'Graphene', u'Graphene Documentation',
author, 'Graphene', 'One line description of project.',
'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
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The basename for the epub file. It defaults to the project name.
# epub_basename = project
# The HTML theme for the epub output. Since the default themes are not
# optimized for small screen space, using the same theme for HTML and epub
# output is usually not wise. This defaults to 'epub', a theme designed to save
# visual space.
#
# epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or 'en' if the language is not set.
#
# epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
# epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#
# epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
#
# epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#
# epub_pre_files = []
# HTML files that should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#
# epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# The depth of the table of contents in toc.ncx.
#
# epub_tocdepth = 3
# Allow duplicate toc entries.
#
# epub_tocdup = True
# Choose between 'default' and 'includehidden'.
#
# epub_tocscope = 'default'
# Fix unsupported image types using the Pillow.
#
# epub_fix_images = False
# Scale large images.
#
# epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# epub_show_urls = 'inline'
# If false, no index is generated.
#
# epub_use_index = True
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}

11
docs/index.rst Normal file
View File

@ -0,0 +1,11 @@
Graphene
========
Contents:
.. toctree::
:maxdepth: 2
quickstart
types/index
relay/index

51
docs/quickstart.rst Normal file
View File

@ -0,0 +1,51 @@
Getting started
===============
Lets build a basic GraphQL schema from scratch.
Requirements
------------
- Python (2.7, 3.2, 3.3, 3.4, 3.5, pypy)
- Graphene (1.0)
Project setup
-------------
.. code:: bash
pip install graphene>=1.0
Creating a basic Schema
-----------------------
A GraphQL schema describes your data model, and provides a GraphQL
server with an associated set of resolve methods that know how to fetch
data.
We are going to create a very simple schema, with a ``Query`` with only
one field: ``hello``. And when we query it should return ``"World"``.
.. code:: python
import graphene
class Query(graphene.ObjectType):
hello = graphene.String()
def resolve_hello(self, args, context, info):
return 'World'
schema = graphene.Schema(query=Query)
Querying
--------
Then, we can start querying our schema:
.. code:: python
result = schema.execute('{ hello }')
print result.data['hello'] # "World"
Congrats! You got your first graphene schema working!

45
docs/relay/connection.rst Normal file
View File

@ -0,0 +1,45 @@
Connection
==========
A connection is a vitaminized version of a List that provides ways of
slicing and paginating through it. The way you create Connection types
in ``graphene`` is using ``relay.Connection`` and ``relay.ConnectionField``.
Quick example
-------------
If we want to create a custom Connection on a given node, we have to subclass the
``Connection`` class.
In the following example, ``extra`` will be an extra field in the connection,
and ``other`` an extra field in the Connection Edge.
.. code:: python
class ShipConnection(Connection):
extra = String()
class Meta:
node = Ship
class Edge:
other = String()
The ``ShipConnection`` connection class, will have automatically a ``pageInfo`` field,
and a ``edges`` field (which is a list of ``ShipConnection.Edge``).
This ``Edge`` will have a ``node`` field linking to the specified node
(in ``ShipConnection.Meta``) and the field ``other`` that we defined in the class.
Connection Field
----------------
You can create connection fields in any Connection, in case any ObjectType
that implements ``Node`` will have a default Connection.
.. code:: python
class Faction(graphene.ObjectType):
name = graphene.String()
ships = relay.ConnectionField(ShipConnection)
def resolve_ships(self, args, context, info):
return []

29
docs/relay/index.rst Normal file
View File

@ -0,0 +1,29 @@
Relay
=====
Graphene has complete support for `Relay`_ and offers some utils to make
integration from Python easy.
.. toctree::
:maxdepth: 2
nodes
connection
mutations
Useful links
------------
- `Getting started with Relay`_
- `Relay Global Identification Specification`_
- `Relay Cursor Connection Specification`_
- `Relay input Object Mutation`_
.. _Relay: https://facebook.github.io/relay/docs/graphql-relay-specification.html
.. _Relay specification: https://facebook.github.io/relay/graphql/objectidentification.htm#sec-Node-root-field
.. _Getting started with Relay: https://facebook.github.io/relay/docs/graphql-relay-specification.html
.. _Relay Global Identification Specification: https://facebook.github.io/relay/graphql/objectidentification.htm
.. _Relay Cursor Connection Specification: https://facebook.github.io/relay/graphql/connections.htm
.. _Relay input Object Mutation: https://facebook.github.io/relay/graphql/mutations.htm

27
docs/relay/mutations.rst Normal file
View File

@ -0,0 +1,27 @@
Mutations
=========
Most APIs dont just allow you to read data, they also allow you to
write. In GraphQL, this is done using mutations. Just like queries,
Relay puts some additional requirements on mutations, but Graphene
nicely manages that for you. All you need to do is make your mutation a
subclass of ``relay.ClientIDMutation``.
.. code:: python
class IntroduceShip(relay.ClientIDMutation):
class Input:
ship_name = graphene.String(required=True)
faction_id = graphene.String(required=True)
ship = graphene.Field(Ship)
faction = graphene.Field(Faction)
@classmethod
def mutate_and_get_payload(cls, input, context, info):
ship_name = input.get('ship_name')
faction_id = input.get('faction_id')
ship = create_ship(ship_name, faction_id)
faction = get_faction(faction_id)
return IntroduceShip(ship=ship, faction=faction)

85
docs/relay/nodes.rst Normal file
View File

@ -0,0 +1,85 @@
Nodes
=====
A ``Node`` is an Interface provided by ``graphene.relay`` that contains
a single field ``id`` (which is a ``ID!``). Any object that inherits
from it have to implement a ``get_node`` method for retrieving a
``Node`` by an *id*.
Quick example
-------------
Example usage (taken from the `Starwars Relay example`_):
.. code:: python
class Ship(graphene.ObjectType):
'''A ship in the Star Wars saga'''
class Meta:
interfaces = (relay.Node, )
name = graphene.String(description='The name of the ship.')
@classmethod
def get_node(cls, id, context, info):
return get_ship(id)
The ``id`` returned by the ``Ship`` type when you query it will be a
scalar which contains the enough info for the server for knowing its
type and its id.
For example, the instance ``Ship(id=1)`` will return ``U2hpcDox`` as the
id when you query it (which is the base64 encoding of ``Ship:1``), and
which could be useful later if we want to query a node by its id.
Custom Nodes
------------
You can use the predefined ``relay.Node`` or you can subclass it, defining
custom ways of how a node id is encoded (using the ``to_global_id`` method in the class)
or how we can retrieve a Node given a encoded id (with the ``get_node_from_global_id`` method).
Example of a custom node:
.. code:: python
class CustomNode(Node):
class Meta:
name = 'Node'
@staticmethod
def to_global_id(type, id):
return '{}:{}'.format(type, id)
@staticmethod
def get_node_from_global_id(global_id, context, info):
type, id = global_id.split(':')
if type == 'User':
return get_user(id)
elif type == 'Photo':
return get_photo(id)
The ``get_node_from_global_id`` method will be called when ``CustomNode.Field`` is resolved.
Node Root field
---------------
As is required in the `Relay specification`_, the server must implement
a root field called ``node`` that returns a ``Node`` Interface.
For this reason, ``graphene`` provides the field ``relay.Node.Field``,
which links to any type in the Schema which implements ``Node``.
Example usage:
.. code:: python
class Query(graphene.ObjectType):
# Should be CustomNode.Field() if we want to use our custom Node
node = relay.Node.Field()
.. _Starwars Relay example: https://github.com/graphql-python/graphene/blob/master/examples/starwars_relay/schema.py

View File

@ -0,0 +1,43 @@
AbstractTypes
=============
An AbstractType contains fields that could be shared among
``graphene.ObjectType``, ``graphene.Interface``,
``graphene.InputObjectType`` or other ``graphene.AbstractType``.
The basics:
- Each AbstractType is a Python class that inherits from ``graphene.AbstractType``.
- Each attribute of the AbstractType represents a field (could be a ``graphene.Field`` or
``graphene.InputField`` depending on where is mounted)
Quick example
-------------
In this example UserFields is an ``AbstractType`` with a name. ``User`` and
``UserInput`` are two types that will have their own fields
plus the ones defined in ``UserFields``.
.. code:: python
import graphene
class UserFields(graphene.AbstractType):
name = graphene.String()
class User(graphene.ObjectType, UserFields):
pass
class UserInput(graphene.InputObjectType, UserFields):
pass
.. code:: graphql
type User {
name: String
}
inputtype UserInput {
name: String
}

67
docs/types/enums.rst Normal file
View File

@ -0,0 +1,67 @@
Enums
=====
A ``Enum`` is a special ``GraphQL`` type that represents a set of
symbolic names (members) bound to unique, constant values.
Definition
----------
You can create an ``Enum`` using classes:
.. code:: python
import graphene
class Episode(graphene.Enum):
NEWHOPE = 4
EMPIRE = 5
JEDI = 6
But also using instances of Enum:
.. code:: python
Episode = graphene.Enum('Episode', [('NEWHOPE', 4), ('EMPIRE', 5), ('JEDI', 6)])
Value descriptions
------------------
It's possible to add a description to a enum value, for that the the enum value
needs to have the ``description`` property on it.
.. code:: python
class Episode(graphene.Enum):
NEWHOPE = 4
EMPIRE = 5
JEDI = 6
@property
def description(self):
if self == Episode.NEWHOPE:
return 'New Hope Episode'
return 'Other episode'
Usage with Python Enums
-----------------------
In case that the Enums are already defined it's possible to reuse them using
the ``Enum.from_enum`` function.
.. code:: python
graphene.Enum.from_enum(AlreadyExistingPyEnum)
Notes
-----
Internally, ``graphene.Enum`` uses `enum.Enum`_ Python
implementation if available, or a backport if not.
So you can use it in the same way as you would do with Python
``enum.Enum``.
.. _``enum.Enum``: https://docs.python.org/3/library/enum.html

13
docs/types/index.rst Normal file
View File

@ -0,0 +1,13 @@
===============
Types Reference
===============
.. toctree::
:maxdepth: 1
enums
scalars
interfaces
abstracttypes
objecttypes
mutations

60
docs/types/interfaces.rst Normal file
View File

@ -0,0 +1,60 @@
Interfaces
==========
An Interface contains the essential fields that will be implemented among
multiple ObjectTypes.
The basics:
- Each Interface is a Python class that inherits from ``graphene.Interface``.
- Each attribute of the Interface represents a GraphQL field.
Quick example
-------------
This example model defines a Character, which has a name. ``Human`` and
``Droid`` are two of the Interface implementations.
.. code:: python
import graphene
class Character(graphene.Interface):
name = graphene.String()
# Human is a Character implementation
class Human(ObjectType):
class Meta:
interfaces = (Character, )
born_in = graphene.String()
# Droid is a Character implementation
class Droid(Character):
class Meta:
interfaces = (Character, )
function = graphene.String()
**name** is a field in the ``Character`` interface that will be in both
``Human`` and ``Droid`` ObjectTypes (as those implement the ``Character``
interface). Each ObjectType also define extra fields at the same
time.
The above types would have the following representation in a schema:
.. code:: graphql
interface Character {
name: String
}
type Droid implements Character {
name: String
function: String
}
type Human implements Character {
name: String
bornIn: String
}

78
docs/types/mutations.rst Normal file
View File

@ -0,0 +1,78 @@
Mutations
=========
A Mutation is a special ObjectType that also defines an Input.
Quick example
-------------
This example defines a Mutation:
.. code:: python
import graphene
class CreatePerson(graphene.Mutation):
class Input:
name = graphene.String()
ok = graphene.Boolean()
person = graphene.Field(lambda: Person)
def mutate(self, args, context, info):
person = Person(name=args.get('name'))
ok = True
return CreatePerson(person=person, ok=ok)
**person** and **ok** are the output fields of the Mutation when is
resolved.
**Input** attributes are the arguments that the Mutation
``CreatePerson`` needs for resolving, in this case **name** will be the
only argument for the mutation.
**mutate** is the function that will be applied once the mutation is
called.
So, we can finish our schema like this:
.. code:: python
# ... the Mutation Class
class Person(graphene.ObjectType):
name = graphene.String()
class MyMutations(graphene.ObjectType):
create_person = CreatePerson.Field()
schema = graphene.Schema(mutation=MyMutations)
Executing the Mutation
----------------------
Then, if we query (``schema.execute(query_str)``) the following:
.. code:: graphql
mutation myFirstMutation {
createPerson(name:"Peter") {
person {
name
}
ok
}
}
We should receive:
.. code:: json
{
"createPerson": {
"person" : {
name: "Peter"
},
"ok": true
}
}

106
docs/types/objecttypes.rst Normal file
View File

@ -0,0 +1,106 @@
ObjectTypes
===========
An ObjectType is the single, definitive source of information about your
data. It contains the essential fields and behaviors of the data youre
querying.
The basics:
- Each ObjectType is a Python class that inherits
``graphene.ObjectType`` or inherits an implemented `Interface`_.
- Each attribute of the ObjectType represents a ``Field``.
Quick example
-------------
This example model defines a Person, which has a first\_name and
last\_name:
.. code:: python
import graphene
class Person(graphene.ObjectType):
first_name = graphene.String()
last_name = graphene.String()
full_name = graphene.String()
def resolve_full_name(self, args, context, info):
return '{} {}'.format(self.first_name, self.last_name)
**first\_name** and **last\_name** are fields of the ObjectType. Each
field is specified as a class attribute, and each attribute maps to a
Field.
The above ``Person`` ObjectType would have the following representation
in a schema:
.. code:: graphql
type Person {
firstName: String
lastName: String
fullName: String
}
Resolvers
---------
A resolver is a method that resolves certain field within a
``ObjectType``. The resolver of a field will be, if not specified
otherwise, the ``resolve_{field_name}`` within the ``ObjectType``.
By default a resolver will take the ``args``, ``context`` and ``info``
arguments.
Quick example
~~~~~~~~~~~~~
This example model defines a ``Query`` type, which has a reverse field
that reverses the given ``word`` argument using the ``resolve_reverse``
method in the class.
.. code:: python
import graphene
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String())
def resolve_reverse(self, args, context, info):
word = args.get('word')
return word[::-1]
Resolvers outside the class
~~~~~~~~~~~~~~~~~~~~~~~~~~~
A field could also specify a custom resolver outside the class:
.. code:: python
import graphene
def reverse(root, args, context, info):
word = args.get('word')
return word[::-1]
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String(), resolver=reverse)
Instances as data containers
----------------------------
Graphene ``ObjectType``\ s could act as containers too. So with the
previous example you could do.
.. code:: python
peter = Person(first_name='Peter', last_name='Griffin')
peter.first_name # prints "Peter"
peter.last_name # prints "Griffin"
.. _Interface: /docs/interfaces/

68
docs/types/scalars.rst Normal file
View File

@ -0,0 +1,68 @@
Scalars
=======
Graphene define the following base Scalar Types:
- ``graphene.String``
- ``graphene.Int``
- ``graphene.Float``
- ``graphene.Boolean``
- ``graphene.ID``
Graphene also provides custom scalars for Dates and JSON:
- ``graphene.types.datetime.DateTime``
- ``graphene.types.json.JSONString``
Custom scalars
--------------
You can create a custom scalar for your schema.
The following is an example for creating a DateTime scalar:
.. code:: python
import datetime
from graphene.core.classtypes import Scalar
from graphql.core.language import ast
class DateTime(Scalar):
'''DateTime Scalar Description'''
@staticmethod
def serialize(dt):
return dt.isoformat()
@staticmethod
def parse_literal(node):
if isinstance(node, ast.StringValue):
return datetime.datetime.strptime(
node.value, "%Y-%m-%dT%H:%M:%S.%f")
@staticmethod
def parse_value(value):
return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
Mounting Scalars
----------------
This scalars if are mounted in a ``ObjectType``, ``Interface`` or
``Mutation``, would act as ``Field``\ s.
.. code:: python
class Person(graphene.ObjectType):
name = graphene.String()
# Is equivalent to:
class Person(graphene.ObjectType):
name = graphene.Field(graphene.String())
If the types are mounted in a ``Field``, would act as ``Argument``\ s.
.. code:: python
graphene.Field(graphene.String(), to=graphene.String())
# Is equivalent to:
graphene.Field(graphene.String(), to=graphene.Argument(graphene.String()))