diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 29051ed..fa4b573 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,7 +3,7 @@ Changelog
Versions follow `Semantic Versioning `_ (``..``).
-v1.3.1 (2020-04-05)
+vTBC (TBC)
-------------------
Features
@@ -11,6 +11,9 @@ Features
* `#197 `: Added
``autoapi.__version__`` and ``autoapi.__version_info__`` attributes
for accessing version information.
+* `#201 `: (Python)
+ Added the ``autoapi_member_order`` option to allow the order that members
+ are documentated to be configurable.
Bug Fixes
^^^^^^^^^
@@ -19,7 +22,7 @@ Bug Fixes
Trivial/Internal Changes
^^^^^^^^^^^^^^^^^^^^^^^^
-
+* black shows diffs by default
v1.3.0 (2020-04-05)
-------------------
diff --git a/autoapi/extension.py b/autoapi/extension.py
index 4cf17b6..e687ffd 100644
--- a/autoapi/extension.py
+++ b/autoapi/extension.py
@@ -290,6 +290,7 @@ def setup(app):
app.add_config_value("autoapi_root", API_ROOT, "html")
app.add_config_value("autoapi_ignore", [], "html")
app.add_config_value("autoapi_options", _DEFAULT_OPTIONS, "html")
+ app.add_config_value("autoapi_member_order", "bysource", "html")
app.add_config_value("autoapi_file_patterns", None, "html")
app.add_config_value("autoapi_dirs", [], "html")
app.add_config_value("autoapi_keep_files", False, "html")
diff --git a/autoapi/mappers/python/mapper.py b/autoapi/mappers/python/mapper.py
index 0767dfa..b7b5044 100644
--- a/autoapi/mappers/python/mapper.py
+++ b/autoapi/mappers/python/mapper.py
@@ -1,5 +1,6 @@
import collections
import copy
+import operator
import os
import sys
@@ -339,4 +340,11 @@ class PythonSphinxMapper(SphinxMapperBase):
child_data, options=options, **kwargs
):
obj.children.append(child_obj)
+
+ # Parser gives children in source order already
+ if self.app.config.autoapi_member_order == "alphabetical":
+ obj.children.sort(key=operator.attrgetter("name"))
+ elif self.app.config.autoapi_member_order == "groupwise":
+ obj.children.sort(key=lambda x: (x.member_order, x.name))
+
yield obj
diff --git a/autoapi/mappers/python/objects.py b/autoapi/mappers/python/objects.py
index 6d418a6..9ae7a83 100644
--- a/autoapi/mappers/python/objects.py
+++ b/autoapi/mappers/python/objects.py
@@ -21,6 +21,7 @@ class PythonPythonMapper(PythonMapperBase):
language = "python"
is_callable = False
+ member_order = 0
def __init__(self, obj, class_content="class", **kwargs):
super(PythonPythonMapper, self).__init__(obj, **kwargs)
@@ -156,6 +157,7 @@ class PythonPythonMapper(PythonMapperBase):
class PythonFunction(PythonPythonMapper):
type = "function"
is_callable = True
+ member_order = 40
def __init__(self, obj, **kwargs):
super(PythonFunction, self).__init__(obj, **kwargs)
@@ -180,6 +182,7 @@ class PythonFunction(PythonPythonMapper):
class PythonMethod(PythonFunction):
type = "method"
is_callable = True
+ member_order = 50
def __init__(self, obj, **kwargs):
super(PythonMethod, self).__init__(obj, **kwargs)
@@ -211,6 +214,7 @@ class PythonData(PythonPythonMapper):
"""Global, module level data."""
type = "data"
+ member_order = 10
def __init__(self, obj, **kwargs):
super(PythonData, self).__init__(obj, **kwargs)
@@ -236,6 +240,7 @@ class PythonAttribute(PythonData):
"""An object/class level attribute."""
type = "attribute"
+ member_order = 10
class TopLevelPythonPythonMapper(PythonPythonMapper):
@@ -290,6 +295,7 @@ class PythonPackage(TopLevelPythonPythonMapper):
class PythonClass(PythonPythonMapper):
type = "class"
+ member_order = 30
def __init__(self, obj, **kwargs):
super(PythonClass, self).__init__(obj, **kwargs)
@@ -374,3 +380,4 @@ class PythonClass(PythonPythonMapper):
class PythonException(PythonClass):
type = "exception"
+ member_order = 20
diff --git a/docs/reference/config.rst b/docs/reference/config.rst
index 0d0c0fa..44ae2eb 100644
--- a/docs/reference/config.rst
+++ b/docs/reference/config.rst
@@ -144,6 +144,22 @@ Customisation Options
docstring is empty and the class defines a ``__new__`` with a docstring,
the ``__new__`` docstring is used instead of the ``__init__`` docstring.
+.. confval:: autoapi_member_order
+
+ Default: ``bysource``
+
+ The order to document members.
+
+ * ``alphabetical``: Order members by their name, case sensitively.
+ * ``bysource``: Order members by the order that they were defined in the source code.
+ * ``groupwise``: Order members by their type then alphabetically, in the order:
+ * Submodules and subpackages
+ * Attributes
+ * Exceptions
+ * Classes
+ * Functions
+ * Methods
+
.. confval:: autoapi_python_use_implicit_namespaces
Default: ``False``
diff --git a/tests/python/test_pyintegration.py b/tests/python/test_pyintegration.py
index 15744c9..f60d29c 100644
--- a/tests/python/test_pyintegration.py
+++ b/tests/python/test_pyintegration.py
@@ -394,6 +394,26 @@ def test_skipping_members(builder):
assert "not ignored" in example_file
+@pytest.mark.parametrize(
+ "value,order",
+ [
+ ("bysource", ["Foo", "decorator_okay", "Bar"]),
+ ("alphabetical", ["Bar", "Foo", "decorator_okay"]),
+ ("groupwise", ["Bar", "Foo", "decorator_okay"]),
+ ],
+)
+def test_order_members(builder, value, order):
+ confoverrides = {"autoapi_member_order": value}
+ builder("pyexample", confoverrides=confoverrides)
+
+ example_path = "_build/text/autoapi/example/index.txt"
+ with io.open(example_path, encoding="utf8") as example_handle:
+ example_file = example_handle.read()
+
+ indexes = [example_file.index(name) for name in order]
+ assert indexes == sorted(indexes)
+
+
class _CompareInstanceType(object):
def __init__(self, type_):
self.type = type_