Skip to content

Commit 7bc9ce0

Browse files
authored
docs: Configure intersphinx to reference Python's and NumPy's docs (#5861)
By enabling the widely used intersphinx functionality, Sphinx is able to resolve types, exceptions, etc. and allows us to create cross-references to the docs of an external project, like the Python standard library. For example, a `:raises OSError: ...` or `:raises ValueError: ...` in the docstrings are magically linked to the Python docs. Same thing for the base classes that come from NumPy. When using cross-refs, I opted to be explicit by using `:external:` followed by the domain and role, so looking like: ``:external:py:func:`sys.exit` ``. It then makes it easier to search for `:external:`, and there's less a surprise that Sphinx links to the python docs when not knowing about it. This comes in as justified when we know we have a couple of classes that override/wrap some python stdlib classes, like our `grass.script.core.Popen`, so being explicit is useful. * docs: Configure intersphinx extension for linking to python library docs * docs: Create external references to python docs in grass.script.core and related docstrings * docs: Add external cross-refs to RegionManager docstrings * docs: Add numpy inventory to intersphinx config
1 parent e2e9b35 commit 7bc9ce0

File tree

5 files changed

+52
-28
lines changed

5 files changed

+52
-28
lines changed

python/grass/app/data.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ def acquire_mapset_lock(
207207
:param env: system environment variables
208208
209209
The function assumes the `GISBASE` variable is in the environment. The variable is
210-
used to find the lock program. If *env* is not provided, `os.environ` is used.
210+
used to find the lock program. If *env* is not provided,
211+
:external:py:data:`os.environ` is used.
211212
"""
212213
if process_id is None:
213214
process_id = os.getpid()

python/grass/docs/conf.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
extensions = [
105105
"sphinx.ext.autodoc",
106106
"sphinx.ext.doctest",
107+
"sphinx.ext.intersphinx",
107108
"sphinx.ext.todo",
108109
"sphinx.ext.coverage",
109110
"sphinx.ext.mathjax",
@@ -498,3 +499,9 @@
498499
"search.html",
499500
"genindex.html",
500501
]
502+
503+
# Intersphinx config
504+
intersphinx_mapping = {
505+
"numpy": ("https://numpy.org/doc/stable/", None),
506+
"python": ("https://docs.python.org/3", None),
507+
}

python/grass/script/core.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ def handle_errors(returncode, result, args, kwargs):
337337
handling mechanism is not desirable or the return code has some
338338
meaning not necessarily interpreted as an error by the caller.
339339
340-
For ``errors="exit"``, ``sys.exit()`` is called with the
340+
For ``errors="exit"``, :external:py:func:`sys.exit()` is called with the
341341
*returncode*, so it behaves similarly to a Bash script with
342342
``set -e``. No additional error message or exception is produced.
343343
This might be useful for a simple script where error message
@@ -477,7 +477,7 @@ def run_command(*args, **kwargs):
477477
478478
This function passes all arguments to ``start_command()``,
479479
then waits for the process to complete. It is similar to
480-
``subprocess.check_call()``, but with the :func:`make_command()`
480+
:external:py:func:`subprocess.check_call()`, but with the :func:`make_command()`
481481
interface. By default, an exception is raised in case of a non-zero
482482
return code by default.
483483
@@ -721,7 +721,8 @@ def exec_command(
721721
:param bool quiet: True to run quietly (<tt>--q</tt>)
722722
:param bool superquiet: True to run quietly (<tt>--qq</tt>)
723723
:param bool verbose: True to run verbosely (<tt>--v</tt>)
724-
:param env: dictionary with system environment variables (`os.environ` by default)
724+
:param env: dictionary with system environment variables
725+
(:external:py:data:`os.environ` by default)
725726
:param list kwargs: module's parameters
726727
727728
"""
@@ -740,7 +741,8 @@ def message(msg, flag=None, env=None):
740741
741742
:param str msg: message to be displayed
742743
:param str flag: flags (given as string)
743-
:param env: dictionary with system environment variables (`os.environ` by default)
744+
:param env: dictionary with system environment variables
745+
(:external:py:data:`os.environ` by default)
744746
"""
745747
run_command("g.message", flags=flag, message=msg, errors="ignore", env=env)
746748

@@ -753,11 +755,13 @@ def debug(msg, debug=1, env=None):
753755
(with `X` set to the debug level specified in the function call).
754756
755757
:param str msg: debugging message to be displayed
756-
:param str debug: debug level (0-5) with the following recommended levels:
757-
Use 1 for messages generated once of few times,
758-
3 for messages generated for each raster row or vector line,
759-
5 for messages generated for each raster cell or vector point.
760-
:param env: dictionary with system environment variables (`os.environ` by default)
758+
:param str debug: debug level (0-5) with the following recommended
759+
levels:
760+
- Use 1 for messages generated once of few times,
761+
- 3 for messages generated for each raster row or vector line,
762+
- 5 for messages generated for each raster cell or vector point.
763+
:param env: dictionary with system environment variables
764+
(:external:py:data:`os.environ` by default)
761765
"""
762766
if debug_level() >= debug:
763767
# TODO: quite a random hack here, do we need it somewhere else too?
@@ -771,7 +775,8 @@ def verbose(msg, env=None):
771775
"""Display a verbose message using `g.message -v`
772776
773777
:param str msg: verbose message to be displayed
774-
:param env: dictionary with system environment variables (`os.environ` by default)
778+
:param env: dictionary with system environment variables
779+
(:external:py:data:`os.environ` by default)
775780
"""
776781
message(msg, flag="v", env=env)
777782

@@ -780,7 +785,8 @@ def info(msg, env=None):
780785
"""Display an informational message using `g.message -i`
781786
782787
:param str msg: informational message to be displayed
783-
:param env: dictionary with system environment variables (`os.environ` by default)
788+
:param env: dictionary with system environment variables
789+
(:external:py:data:`os.environ` by default)
784790
"""
785791
message(msg, flag="i", env=env)
786792

@@ -799,7 +805,8 @@ def percent(i, n, s, env=None):
799805
:param int i: current item
800806
:param int n: total number of items
801807
:param int s: increment size
802-
:param env: dictionary with system environment variables (`os.environ` by default)
808+
:param env: dictionary with system environment variables
809+
(:external:py:data:`os.environ` by default)
803810
"""
804811
message("%d %d %d" % (i, n, s), flag="p", env=env)
805812

@@ -808,7 +815,8 @@ def warning(msg, env=None):
808815
"""Display a warning message using `g.message -w`
809816
810817
:param str msg: warning message to be displayed
811-
:param env: dictionary with system environment variables (`os.environ` by default)
818+
:param env: dictionary with system environment variables
819+
(:external:py:data:`os.environ` by default)
812820
"""
813821
message(msg, flag="w", env=env)
814822

@@ -821,7 +829,8 @@ def error(msg, env=None):
821829
For error handling using the standard mechanism use :func:`fatal()`.
822830
823831
:param str msg: error message to be displayed
824-
:param env: dictionary with system environment variables (`os.environ` by default)
832+
:param env: dictionary with system environment variables
833+
(:external:py:data:`os.environ` by default)
825834
"""
826835
message(msg, flag="e", env=env)
827836

@@ -830,11 +839,12 @@ def fatal(msg, env=None):
830839
"""Display an error message using `g.message -e`, then abort or raise
831840
832841
Raises exception when module global raise_on_error is 'True', abort
833-
(calls exit) otherwise.
842+
(calls :external:py:func:`sys.exit`) otherwise.
834843
Use :func:`set_raise_on_error()` to set the behavior.
835844
836845
:param str msg: error message to be displayed
837-
:param env: dictionary with system environment variables (`os.environ` by default)
846+
:param env: dictionary with system environment variables
847+
(:external:py:data:`os.environ` by default)
838848
"""
839849
global raise_on_error
840850
if raise_on_error:
@@ -847,8 +857,9 @@ def fatal(msg, env=None):
847857
def set_raise_on_error(raise_exp=True):
848858
"""Define behaviour on fatal error (fatal() called)
849859
850-
:param bool raise_exp: True to raise ScriptError instead of calling
851-
sys.exit(1) in fatal()
860+
:param bool raise_exp: True to raise :py:exc:`~grass.exceptions.ScriptError`
861+
instead of calling :external:py:func:`sys.exit(1) <sys.exit>`
862+
in :py:func:`~grass.script.core.fatal`
852863
853864
:return: current status
854865
"""
@@ -859,8 +870,9 @@ def set_raise_on_error(raise_exp=True):
859870

860871

861872
def get_raise_on_error():
862-
"""Return True if a ScriptError exception is raised instead of calling
863-
sys.exit(1) in case a fatal error was invoked with fatal()
873+
"""Return True if a :py:exc:`~grass.exceptions.ScriptError` exception is raised
874+
instead of calling :external:py:func:`sys.exit(1) <sys.exit>` in case a fatal error
875+
was invoked with :py:func:`~grass.script.core.fatal`.
864876
"""
865877
global raise_on_error
866878
return raise_on_error
@@ -872,10 +884,10 @@ def set_capture_stderr(capture=True):
872884
873885
By default, standard error output (stderr) of child processes shows
874886
in the same place as output of the parent process. This may not
875-
always be the same place as ``sys.stderr`` is written.
876-
After calling this function, functions in the ``grass.script``
887+
always be the same place as :external:py:data:`sys.stderr` is written.
888+
After calling this function, functions in the :py:mod:`grass.script`
877889
package will capture the stderr of child processes and pass it
878-
to ``sys.stderr`` if there is an error.
890+
to :external:py:data:`sys.stderr` if there is an error.
879891
880892
.. note::
881893
@@ -1237,7 +1249,8 @@ def gisenv(env: _Env | None = None) -> KeyValue[str | None]:
12371249
>>> print(env["GISDBASE"]) # doctest: +SKIP
12381250
/opt/grass-data
12391251
1240-
:param env: dictionary with system environment variables (`os.environ` by default)
1252+
:param env: dictionary with system environment variables
1253+
(:external:py:data:`os.environ` by default)
12411254
:return: list of GRASS variables
12421255
"""
12431256
s = read_command("g.gisenv", flags="n", env=env)

python/grass/script/raster.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,8 @@ def __init__(self, env: dict[str, str] | None = None, **kwargs):
459459
"""
460460
Initializes the MaskManager.
461461
462-
:param env: Environment to use. Defaults to modifying os.environ.
462+
:param env: Environment to use.
463+
Defaults to modifying :external:py:data:`os.environ`.
463464
:param kwargs: Keyword arguments passed to `g.region`
464465
"""
465466
self.env = env if env is not None else os.environ
@@ -543,7 +544,8 @@ def __init__(self, env: dict[str, str] | None = None, **kwargs):
543544
"""
544545
Initializes the MaskManager.
545546
546-
:param env: Environment to use. Defaults to modifying os.environ.
547+
:param env: Environment to use.
548+
Defaults to modifying :external:py:data:`os.environ`.
547549
:param kwargs: Keyword arguments passed to `g.region`
548550
"""
549551
self.env = env if env is not None else os.environ

python/grass/script/setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ class SessionHandle:
409409
pass
410410
# session ends automatically here when outside of the "with" block
411411
412-
The example above is modifying the global, process environment (`os.environ`).
412+
The example above is modifying the global, process environment
413+
(:external:py:data:`os.environ`).
413414
If you don't want to modify the global environment, use the _env_ parameter
414415
for the _init_ function to modify the provided environment instead.
415416
This environment is then available as an attribute of the session object.

0 commit comments

Comments
 (0)