Update API documentation

Implement a new system combining Doxygen with Sphinx using Breathe.
This commit is contained in:
Oliver Hamlet
2016-08-24 08:08:12 +01:00
parent 332b86c38b
commit 9c04741de2
21 changed files with 3553 additions and 378 deletions
+2477
View File
File diff suppressed because it is too large Load Diff
+348
View File
@@ -0,0 +1,348 @@
# -*- coding: utf-8 -*-
#
# LOOT API documentation build configuration file, created by
# sphinx-quickstart on Sat Aug 13 21:09:25 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',
'breathe',
]
# 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'LOOT API'
copyright = u'2016, WrinklyNinja'
author = u'WrinklyNinja'
# 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'latest'
# The full version, including alpha/beta/rc tags.
release = u'latest'
# 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 = []
# 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 = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# 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'LOOT API v0.9.2'
# 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 = []
# 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 = 'LOOTAPIdoc'
# -- 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, 'LOOTAPI.tex', u'LOOT API Documentation',
u'WrinklyNinja', '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, 'lootapi', u'LOOT API 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, 'LOOTAPI', u'LOOT API Documentation',
author, 'LOOTAPI', '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
breathe_projects = {
"loot_api":"../../build/documentation/xml/",
}
breathe_default_project = 'loot_api'
+52
View File
@@ -0,0 +1,52 @@
*******************
Credits & Copyright
*******************
The LOOT API is written by `WrinklyNinja`_ in C++ and makes use of the
`Boost`_, `libespm`_, `libgit2`_, `libloadorder`_, `Pseudosem`_ and `yaml-cpp`_
libraries. The copyright licenses for all of these and the LOOT API itself are
included below.
.. _WrinklyNinja: https://github.com/WrinklyNinja
.. _Boost: http://www.boost.org/
.. _libespm: https://github.com/WrinklyNinja/libespm
.. _libgit2: https://github.com/libgit2/libgit2
.. _libloadorder: https://github.com/WrinklyNinja/libloadorder
.. _Pseudosem: https://github.com/WrinklyNinja/pseudosem
.. _yaml-cpp: https://github.com/WrinklyNinja/yaml-cpp
Boost
=====
.. include:: ../licenses/Boost Software License v1.0.txt
:literal:
libgit2
=======
.. include:: ../licenses/GNU GPL v2 (libgit2).txt
:literal:
LOOT, Libespm & Libloadorder
============================
.. include:: ../licenses/GNU GPL v3.txt
:literal:
LOOT Documentation
==================
.. include:: ../licenses/GNU FDL v1.3.txt
:literal:
Pseudosem
=========
.. include:: ../licenses/MIT License (Pseudosem).txt
:literal:
yaml-cpp
========
.. include:: ../licenses/MIT License (yaml-cpp).txt
:literal:
+77
View File
@@ -0,0 +1,77 @@
***************
Version History
***************
0.9.2 - *3 August 2016*
=======================
* Fixed the wrong API binary being packaged. This caused the v0.9.0 and v0.9.1
API releases to actually be re-releases of a snapshot build made at some
point between v0.8.1 and v0.9.0: the affected API releases were taken
offline once this was discovered.
* Fixed ``loot_get_plugin_tags()`` remembering results and including them in the
results of subsequent calls.
* Fixed an error occurring when the user's temporary files directory didn't
exist and updating the masterlist tried to create a directory there.
* Fixed errors when reading some Oblivion plugins during sorting, including
the official DLC.
* libespm (2.5.5) and Pseudosem (1.1.0) dependencies have been updated to the
versions given in brackets.
0.9.1 - *23 June 2016*
======================
* No API changes.
0.9.0 - *21 May 2016*
=====================
* Moved API header location to the more standard ``include/loot/api.h``.
* Documented LOOT's masterlist versioning system.
* Made all API outputs fully const to make it clear they should not be
modified and to avoid internal const casting.
* Removed the ``loot_cleanup()`` function, as the one string it used to destroy
is now stored on the stack and so destroyed when the API is unloaded.
* The ``loot_db`` type is now an opaque struct, and functions that used to take
it as a value now take a pointer to it.
* Removed the ``loot_lang_any`` constant. The ``loot_lang_english`` constant
should be used instead.
0.8.1 - *27 September 2015*
===========================
* Fixed crash when loading plugins due to lack of thread safety.
* Fixed masterlist updater and validator not checking for valid condition
and regex syntax.
* Check for safe file paths when parsing conditions.
* Updated Boost (1.59.0), libgit2 (0.23.2) and CEF (branch 2454) dependencies.
This fixes the masterlist updater not working correctly for Windows Vista
users.
0.8.0 - *22 July 2015*
======================
* Fixed many miscellaneous bugs, including initialisation crashes and
incorrect metadata input/output handling.
* Fixed LOOT silently discarding some non-unique metadata: an error will now
occur when loading or attempting to apply such metadata.
* Fixed and improved LOOT's version comparison behaviour for a wide variety of
version string formats. This involved removing LOOT's usage of the Alphanum
code library.
* Improved plugin loading performance for computers with weaker multithreading
capabilities (eg. non-hyperthreaded dual-core or single-core CPUs).
* LOOT no longer outputs validity warnings for inactive plugins.
* Metadata syntax support changes, see the metadata syntax document for
details.
* Updated libgit2 to v0.23.0.
0.7.1 - *22 June 2015*
======================
* Fixed "No existing load order position" errors when sorting.
* Fixed output of Bash Tag removal suggestions in ``loot_write_minimal_list()``.
0.7.0 - *20 May 2015*
=====================
* Initial API release.
+12
View File
@@ -0,0 +1,12 @@
########
LOOT API
########
.. toctree::
introduction
miscellaneous
sorting
reference
history
credits
+14
View File
@@ -0,0 +1,14 @@
Introduction
============
LOOT is a utility that helps users avoid serious conflicts between their mods by
setting their plugins in an optimal load order. It also provides tens of
thousands of plugin-specific messages, including usage notes, requirements,
incompatibilities, bug warnings and installation mistake notifications, and
thousands of Bash Tag suggestions.
This metadata that LOOT supplies is stored in its masterlist, which is
maintained by the LOOT team using information provided by mod authors and users.
Users can also add to and modify the metadata used by LOOT through the use of
userlist files. The LOOT API provides a way for third-party developers to access
this metadata for use in their own programs.
+71
View File
@@ -0,0 +1,71 @@
*********************
Miscellaneous Details
*********************
String Encoding
===============
* All output strings are encoded in UTF-8.
* Input strings are expected to be encoded in UTF-8.
* File paths are case-sensitive if and only if the underlying file system is
case-sensitive.
* :cpp:func:`WriteMinimalList` writes a metadata list encoded in UTF-8.
Errors
======
All errors encountered are thrown as exceptions that inherit from
``std::exception``.
Metadata Files
==============
LOOT stores plugin metadata in YAML files. It distinguishes between *masterlist*
and *userlist* files: each game has a single masterlist, which is a public,
curated metadata store, and each LOOT user has a private userlist, which can
contain metadata added by the user. The two files use the same `syntax`_, but
metadata in the userlist extends or replaces metadata sourced from the
masterlist.
LOOT's plugin metadata can be conditional, eg. a plugin may require a patch only
if another plugin is also present. The API's :cpp:func:`LoadLists` method parses
metadata files into memory, but does not evaluate these conditions, so the
loaded metadata may contain metadata that is invalid for the installed game that
the :cpp:class:`loot::DatabaseInterface` object being operated on was created for.
The :cpp:func:`EvalLists` must be called to evaluate any conditions in the
loaded metadata. In doing so it discards any metadata with a condition that
evaluates to false, but the pre-evaluation metadata is cached internally so that
re-evaluation does not require the lists to be reloaded.
.. _syntax: https://loot.github.io/docs/0.9.2/LOOT%20Metadata%20Syntax.html
Caching
=======
All unevaluated metadata is cached between calls to :cpp:func:`LoadLists`.
Evaluated metadata is cached between calls to :cpp:func:`EvalLists`. Metadata
conditions and their results are cached between calls to :cpp:func:`EvalLists`,
so that every call to :cpp:func:`EvalLists` re-evaluates all conditions, but
conditions that are used more than once in the loaded metadata are only
evaluated once.
Plugin content is cached between calls to :cpp:func:`SortPlugins`, though no
other API function makes use of it.
Performance
===========
Loading metadata lists is a relatively costly operation, as is updating the
masterlist (which involves loading it). Evaluating the loaded metadata lists is
not very costly relative to loading them, though is performance depends on the
type and number of conditions used in the loaded metadata, and all the
conditions involve filesystem access.
Sorting plugins is expensive, as it involves loading all the FormIDs for all
the plugins, apart from the game's main master file, which is skipped as an
optimisation (it doesn't depend on anything else and is much bigger than any
other plugin, so is unnecessary and slow to load).
Getting plugin metadata once loaded is cheap, as is getting a masterlist's
revision.
+47
View File
@@ -0,0 +1,47 @@
*************
API Reference
*************
.. contents::
Enumerations
============
.. doxygenenum:: loot::GameType
.. doxygenenum:: loot::LanguageCode
.. doxygenenum:: loot::MessageType
.. doxygenenum:: loot::PluginCleanliness
Public-Field Data Structures
============================
.. doxygenstruct:: loot::MasterlistInfo
:members:
.. doxygenstruct:: loot::PluginMessage
:members:
.. doxygenstruct:: loot::PluginTags
:members:
Functions
=========
.. doxygenfunction:: loot::IsCompatible
.. doxygenfunction:: loot::CreateDatabase
Interfaces
==========
.. doxygenclass:: loot::DatabaseInterface
:members:
Classes
=======
.. doxygenclass:: loot::LootVersion
:members:
+111
View File
@@ -0,0 +1,111 @@
************************
LOOT's Sorting Algorithm
************************
LOOT's sorting algorithm consists of four stages:
.. contents::
:local:
Load plugin data
================
In this first stage, the plugins to be sorted are parsed and their FormIDs
stored. Parsing is multithreaded by dividing the plugins into buckets with
roughly equal total file sizes, and loading each bucket's plugins in a separate
thread. The number of buckets created is equal to the number of concurrent
threads that are hardware-supported (e.g. a dual-core CPU without hyperthreading
may report that it supports two threads).
When parsing plugins, all subrecords are skipped over for efficiency, apart from
the subrecords of the ``TES4`` header record.
Create plugin graph vertices
=================================
Once loaded, a directed graph is created and the plugins are added to it in
lexicographical order as vertices. Any metadata a plugin has in the masterlist
and userlist are then merged into its vertex's data store, and any metadata
conditions evaluated.
Create plugin graph edges
==============================
In this section, the terms *vertex* and *plugin* are used interchangeably, and
the iteration order 'for each plugin' is the order in which the vertices were
added to the graph.
For each plugin:
1. If the plugin is a master file, add edges going to all non-master files. If
the plugin is a non-master file, add edges coming from all master files.
2. Add edges coming from all the plugin's masters. Missing masters have no edges
added.
3. Add edges coming from all the plugin's requirements. Missing requirements
have no edges added.
4. Add edges coming from all the plugin's load after files that are installed
plugins.
At this point, all explicit interdependencies have been graphed. Plugin priority
metadata values must now be propagated down the dependency trees to ensure that
priority edges are added correctly later in the process. To do this:
1. Create a list of all vertices with a global or non-global priority value
greater than zero.
2. Sort the list in order of decreasing priority value.
3. For each vertex, perform a depth-first search, setting priorities at each
vertex visited until equal or larger values are encountered.
Now that the priorities have been propagated, the priority edges can be added.
For each plugin, if it has a global priority value of zero, overrides no records
and loads no archive, skip it, otherwise iterate over all other plugins and:
* If the other plugin's global and non-global priority values equal the
plugin's own values, or if both plugins have a global priority of zero and
have no FormIDs in common, skip the other plugin.
* Otherwise, add an edge from the plugin with lower global priority to the
plugin with higher global priority, if that edge does not cause a cycle. A
cycle is caused if a circular dependency is introduced, for example for two
vertices A and B, A -> B -> A is a cycle.
If the global priorities are equal, compare the non-global priorities
instead.
Plugin overlap edges are then added. Two plugins overlap if they contain the
same FormID, i.e. if they both edit the same record or if one edits a record the
other plugin adds.
For each plugin, skip it if it overrides no records, otherwise iterate over all
other plugins.
* If the plugin and other plugin override the same number of records, or do not
overlap, skip the other plugin.
* Otherwise, add an edge from the plugin which overrides more records to the
plugin that overrides fewer records, unless that edge would cause a cycle.
Finally, tie-break edges are added to ensure that sorting is consistent. For
each plugin, iterate over all other plugins and add an edge between each pair of
plugins in the direction given by the tie-break comparison function, unless that
edge would cause a cycle.
The tie-break comparison function compares current plugin load order positions,
falling back to plugin names.
* If both plugins have positions in the current load order, the function
preserves their existing relative order.
* If one plugin has a position and the other does not, the edge added goes from
the plugin with a position to the plugin without a position.
* If neither plugin has a load order position, a case-insensitive
lexicographical comparison of their filenames without file extensions is used
to decide their order.
Topologically sort the plugin graph
===================================
Note that edges for explicit interdependencies are the only edges allowed to
create cycles: this is because the first step of this stage is to check the
plugin graph for cycles, and throw an error if any are encountered, so that
metadata (or indeed plugin data) that cause them can be corrected.
Once the graph is confirmed to be cycle-free, a topological sort is performed on
the graph, outputting a list of plugins in their newly-sorted load order.