Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/doc_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:
. doc_env/bin/activate
python3 -m pip install -r doc/requirements.txt
python3 -m pip install setuptools
python3 -m pip install pytest
echo PATH=$PATH >> $GITHUB_ENV

- name: Build GDAL
Expand Down Expand Up @@ -73,11 +74,19 @@ jobs:
if find . -name '*.rst' | xargs grep "\.\.warning"; then echo 'Wrong annotation. Should be .. warning'; false; fi
if find . -name '*.rst' | xargs grep "\.\.codeblock"; then echo 'Wrong annotation. Should be .. codeblock'; false; fi
working-directory: ./doc

- name: Doxygen
shell: bash -l {0}
run: |
cmake --build . --target doxygen_xml
working-directory: build

- name: Test documentation examples
shell: bash -l {0}
run: |
ctest -V -R doc-examples --output-on-failure
working-directory: build

- name: Spelling
shell: bash -l {0}
run: |
Expand Down
9 changes: 9 additions & 0 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,13 @@ if (BUILD_DOCS)
-D html_extra_path=extra_path
)

add_test(NAME doc-examples
COMMAND ${CMAKE_COMMAND} -E env ${BUILD_RUN_ENV}
${Python_EXECUTABLE} -m pytest -v --doctest-modules
${CMAKE_BINARY_DIR}/swig/python/osgeo/gdal.py
${CMAKE_BINARY_DIR}/swig/python/osgeo/gdal_array.py
${CMAKE_BINARY_DIR}/swig/python/osgeo/ogr.py
${CMAKE_BINARY_DIR}/swig/python/osgeo/osr.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})

endif ()
60 changes: 60 additions & 0 deletions doc/source/_extensions/doctestplus_gdal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This is a set of three directives that allow us to insert metadata
about doctests into the .rst files so the testing framework knows
which tests to skip.

This is quite different from the doctest extension in Sphinx itself,
which actually does something. For astropy, all of the testing is
centrally managed from py.test and Sphinx is not used for running
tests.
"""
import re

from docutils.nodes import literal_block
from docutils.parsers.rst import Directive


class DoctestSkipDirective(Directive):
has_content = True

def run(self):
# Check if there is any valid argument, and skip it. Currently only
# 'win32' is supported.
if re.match("win32", self.content[0]):
self.content = self.content[2:]
code = "\n".join(self.content)
return [literal_block(code, code)]


class DoctestOmitDirective(Directive):
has_content = True

def run(self):
# Simply do not add any content when this directive is encountered
return []


class DoctestRequiresDirective(DoctestSkipDirective):
# This is silly, but we really support an unbounded number of
# optional arguments
optional_arguments = 64


def setup(app):

app.add_directive("doctest-requires", DoctestRequiresDirective)
app.add_directive("doctest-requires-all", DoctestRequiresDirective)
app.add_directive("doctest-skip", DoctestSkipDirective)
app.add_directive("doctest-skip-all", DoctestSkipDirective)
app.add_directive("doctest", DoctestSkipDirective, override=True)
app.add_directive("doctest-remote-data", DoctestSkipDirective)
app.add_directive("doctest-remote-data-all", DoctestSkipDirective)
# Code blocks that use this directive will not appear in the generated
# documentation. This is intended to hide boilerplate code that is only
# useful for testing documentation using doctest, but does not actually
# belong in the documentation itself.
app.add_directive("testsetup", DoctestOmitDirective, override=True)
app.add_directive("testcleanup", DoctestOmitDirective, override=True)

return {"parallel_read_safe": True, "parallel_write_safe": True}
1 change: 1 addition & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def check_python_bindings():
"configoptions",
"driverproperties",
"cli_example",
"doctestplus_gdal",
"source_file",
"sphinx.ext.napoleon",
"sphinxcontrib.jquery",
Expand Down
7 changes: 4 additions & 3 deletions swig/include/Operations.i
Original file line number Diff line number Diff line change
Expand Up @@ -1015,9 +1015,10 @@ def SuggestedWarpOutput(*args):
Example
-------

>>> ds = gdal.Open("my.tif")
... res = gdal.SuggestedWarpOutput(ds, ["DST_SRS=EPSG:4326"])
... print(res.width, res.height, res.xmin, res.ymin, res.xmax, res.ymax, res.geotransform)
>>> ds = gdal.Open("byte.tif")
>>> res = gdal.SuggestedWarpOutput(ds, ["DST_SRS=EPSG:4326"])
>>> print(res.width, res.height, res.xmin, res.ymin, res.xmax, res.ymax, res.geotransform)
22 18 -117.642 33.891 -117.629 33.902 (-117.642, 0.000598, 0.0, 33.902, 0.0, -0.000598)

"""
if isinstance(args[1], GDALTransformerInfoShadow):
Expand Down
44 changes: 8 additions & 36 deletions swig/include/python/docs/gdal_algorithm_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ list
Example
-------
>>> alg = gdal.Algorithm("raster", "convert")
>>> alg.GetArgNames()
['help', 'help-doc', 'json-usage', 'config', 'quiet', 'progress', 'output-format', 'open-option', 'input-format', 'input', 'output', 'creation-option', 'overwrite', 'append']
>>> sorted(alg.GetArgNames())
['append', 'config', 'creation-option', ..., 'progress', 'quiet']


};

Expand Down Expand Up @@ -143,7 +144,7 @@ Example
-------
>>> alg = gdal.Algorithm("raster")
>>> alg.GetSubAlgorithmNames()
['aspect', 'calc', 'clean-collar', 'clip', 'color-map', 'color-merge', 'contour', 'convert', 'create', 'edit', 'fill-nodata', 'footprint', 'hillshade', 'index', 'info', 'mosaic', 'nodata-to-alpha', 'overview', 'pansharpen', 'pipeline', 'pixel-info', 'polygonize', 'proximity', 'reclassify', 'reproject', 'resize', 'rgb-to-palette', 'roughness', 'scale', 'select', 'set-type', 'sieve', 'slope', 'stack', 'tile', 'tpi', 'tri', 'unscale', 'update', 'viewshed']
['as-features', 'aspect', ..., 'update', 'viewshed']

};

Expand Down Expand Up @@ -201,11 +202,11 @@ Example
'required': True,
'type': 'dataset_list'},
{'category': 'Base',
'description': 'Layer name',
'description': 'Input layer name',
'max_count': 2147483647,
'min_count': 0,
'mutual_exclusion_group': 'layer-sql',
'name': 'layer',
'name': 'input-layer',
'packed_values_allowed': True,
'repeated_arg_allowed': True,
'required': False,
Expand Down Expand Up @@ -305,7 +306,7 @@ Example
-------
>>> alg = gdal.Algorithm("raster")
>>> alg.InstantiateSubAlgorithm("convert")
<osgeo.gdal.Algorithm; proxy of <Swig Object of type 'GDALAlgorithmHS *' at 0x7ca38a3eec40> >
<osgeo.gdal.Algorithm; proxy of <Swig Object of type 'GDALAlgorithmHS *' at ...> >
>>> subalg = alg.InstantiateSubAlgorithm("does_not_exist")

};
Expand Down Expand Up @@ -352,35 +353,6 @@ bool

};

%feature("docstring") Run {

Run an algorithm and report on its success or failure.

Parameters
----------
callback : function
Optional progress callback function
callback_data
Optional value to be provided as final argument to callback function

Returns
-------
bool
``True`` if the algorithm succeeded, ``False`` otherwise

Examples
--------
>>> alg = gdal.Algorithm("vector", "info")
>>> alg['input'] = 'poly.shp'
>>> alg.Run()
True
>>> alg['input'] = 'does_not_exist.shp'
>>> alg.Run()
ERROR 4: does_not_exist.shp: No such file or directory
False

};

};

%feature("docstring") GDALAlgorithmRegistryHS {
Expand Down Expand Up @@ -431,7 +403,7 @@ Examples

>>> subalg = gdal.GetGlobalAlgorithmRegistry().InstantiateAlg('raster').InstantiateSubAlgorithm('polygonize')
>>> subalg.GetArgNames()
['help', 'help-doc', 'json-usage', 'config', 'quiet', 'progress', 'output-format', 'open-option', 'input-format', 'input', 'output', 'creation-option', 'layer-creation-option', 'overwrite', 'update', 'overwrite-layer', 'append', 'layer', 'band', 'attribute-name', 'connect-diagonal-pixels']
['help', 'help-doc', 'json-usage', 'config', 'quiet', 'progress', 'output-format', 'open-option', 'input-format', 'input', 'output', 'creation-option', 'layer-creation-option', 'overwrite', 'update', 'overwrite-layer', 'append', 'output-layer', 'band', 'attribute-name', 'connect-diagonal-pixels']

};

Expand Down
4 changes: 2 additions & 2 deletions swig/include/python/docs/gdal_band_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ list

Examples
--------
>>> import numpy as np
>>> np.random.seed(123)
>>> ds = gdal.GetDriverByName('MEM').Create('', 10, 10, eType=gdal.GDT_Float32)
>>> ds.WriteArray(np.random.normal(size=100).reshape(10, 10))
0
>>> ds.GetRasterBand(1).GetHistogram(min=-3.5, max=3.5, buckets=13, approx_ok=False)
[0, 0, 3, 9, 13, 12, 25, 22, 9, 6, 0, 1, 0] # random
[0, 2, 1, 6, 17, 18, 13, 14, 16, 8, 5, 0, 0]
";

%feature("docstring") GetMaskBand "
Expand Down
4 changes: 2 additions & 2 deletions swig/include/python/docs/gdal_dataset_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ Examples
>>> with gdal.Open('byte.tif') as ds:
... ds.GetExtent(osr.SpatialReference(epsg=9311))
...
(-1621602.9829031324, -1620214.937944802, -1064263.0904900103, -1062837.1327964044)
(-1621603.0, -1620214.9, -1064263.1, -1062837.1)

See Also
--------
Expand Down Expand Up @@ -347,7 +347,7 @@ Examples
>>> with gdal.Open('byte.tif') as ds:
... ds.GetExtentWGS84LongLat()
...
(-117.64204279334717, -117.6289845627537, 33.891546129503816, 33.90243533203516)
(-117.642, -117.629, 33.892, 33.902)

See Also
--------
Expand Down
11 changes: 7 additions & 4 deletions swig/include/python/docs/gdal_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,15 @@ See :cpp:func:`GDALGetDriverCount`.

Examples
--------

.. testsetup::
>>> pytest.skip()

>>> gdal.GetDriverCount()
227
>>> gdal.GetDriverByName('ESRI Shapefile').Deregister()
>>> 124
>>> gdal.GetDriverByName('MapInfo File').Deregister()
>>> gdal.GetDriverCount()
226

>>> 123
";

// gdal.GetGlobalConfigOption
Expand Down
4 changes: 4 additions & 0 deletions swig/include/python/docs/gdal_driver_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ Dataset

Examples
--------
.. testsetup::
>>> if gdal.GetDriverByName('netCDF') is None:
... pytest.skip()

>>> with gdal.GetDriverByName('netCDF').CreateMultiDimensional('test.nc') as ds:
... gdal.MultiDimInfo(ds)
...
Expand Down
Loading
Loading