Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/workflows/build_docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
python-version: "3.13"
cache: "pip"
cache-dependency-path: "setup.cfg"

Expand All @@ -32,7 +32,7 @@ jobs:
uv pip install --system wheel

- name: Install documenteer
run: uv pip install --system 'documenteer[pipelines]==0.8.2' sphinx-automodapi==0.19 sphinx-prompt==1.6.0
run: uv pip install --system -r doc/requirements.txt

- name: Install dependencies
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ config.log
*.so
*.cfgc
*.pyc
doc/api
doc/html
doc/xml
doc/*.tag
Expand Down
26 changes: 3 additions & 23 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,8 @@

This configuration only affects single-package Sphinx documenation builds.
"""
# ruff: noqa: F403, F405

from documenteer.conf.pipelinespkg import * # noqa: F403, import *
from documenteer.conf.guide import *

project = "utils"
html_theme_options["logotext"] = project # noqa: F405, unknown name
html_title = project
html_short_title = project
doxylink = {}
exclude_patterns = ["changes/*"]
nitpick_ignore_regex = [
("py:.*", r"lsst\..*"), # Ignore warnings from links to other lsst packages.
("py:.*", "cProfile.Profile"), # Link does not resolve to py3 docs.
("py:class", "a set-like.*"), # collections.abc.Mapping inheritance.
("py:class", "a shallow copy.*"), # collections.abc.Mapping inheritance.
("py:class", r"None\. .*"), # collections.abc.Mapping inheritance.
("py:class", "an object providing.*"), # collections.abc.Mapping inheritance.
]
nitpick_ignore = [
("py:class", "module"), # Sphinx has problems with types.ModuleType.
("py:obj", "logging.DEBUG"), # Python 3 constant can not be found.
("py:class", "unittest.case.TestCase"), # Sphinx can not see TestCase.
("py:obj", "deprecated.sphinx.deprecated"), # No intersphinx for deprecated package.
("py:class", "LsstLoggers"), # Sphinx does not understand type aliases
("py:obj", "structlog"), # structlog does not have intersphinx mapping.
]
exclude_patterns.append("changes/*")
32 changes: 32 additions & 0 deletions doc/documenteer.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[project]
title = "lsst-utils"

[project.python]
package = "lsst-utils"

[build]
clean = true

[sphinx]
nitpick_ignore = [
["py:class", "module"], # Sphinx has problems with types.ModuleType.
["py:obj", "logging.DEBUG"], # Python 3 constant can not be found.
["py:class", "unittest.case.TestCase"], # Sphinx can not see TestCase.
["py:obj", "deprecated.sphinx.deprecated"], # No intersphinx for deprecated package.
["py:class", "LsstLoggers"], # Sphinx does not understand type aliases
["py:obj", "structlog"], # structlog does not have intersphinx mapping.
["py:class", "array-like"],
["py:class", "scalar"],
]
nitpick_ignore_regex = [
['py:.*', 'lsst\..*'], # Ignore warnings from links to other lsst packages.
['py:.*', 'cProfile.Profile'], # Link does not resolve to py3 docs.
['py:class', 'a set-like.*'], # collections.abc.Mapping inheritance.
['py:class', 'a shallow copy.*'], # collections.abc.Mapping inheritance.
['py:class', 'None\. .*'], # collections.abc.Mapping inheritance.
['py:class', 'an object providing.*'], # collections.abc.Mapping inheritance.
]

[sphinx.intersphinx.projects]
astropy = "https://docs.astropy.org/en/stable"
python = "https://docs.python.org/3"
2 changes: 2 additions & 0 deletions doc/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
documenteer[guide] > 2.0, <3.0
lsst-sphinxutils @ git+https://github.com/lsst/sphinxutils@main
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies = [
dynamic = ["version"]
[project.urls]
"Homepage" = "https://github.com/lsst/utils"
"Source" = "https://github.com/lsst/utils"
[project.optional-dependencies]
test = [
"pytest >= 3.2",
Expand Down
8 changes: 4 additions & 4 deletions python/lsst/utils/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,19 @@ def deprecate_pybind11(obj: Any, reason: str, version: str, category: type[Warni

Parameters
----------
obj : function, method, or class
obj : `~collections.abc.Callable`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it's an improvement in a lot of cases here, this new rigidity does make me sad (I like "convertible to ResourcePath" as a type, for example). Not much we can do about it, I imagine.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did add array-like to the ignore list because fixing all those seemed a step too far.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's an ignore list we can add our own exceptions to then I'm totally happy with this change. I'm all for better guards against non-types due to mispellings, as long as we can carve out exceptions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It's in the documenteer.toml file.

The function, method, or class to deprecate.
reason : `str`
Reason for deprecation, passed to `~deprecated.sphinx.deprecated`.
version : 'str'
version : `str`
Next major version in which the interface will be deprecated,
passed to `~deprecated.sphinx.deprecated`.
category : `Warning`
Warning category, passed to `~deprecated.sphinx.deprecated`.

Returns
-------
obj : function, method, or class
obj : `~collections.abc.Callable`
Wrapped function, method, or class.

Examples
Expand Down Expand Up @@ -88,7 +88,7 @@ def suppress_deprecations(category: type[Warning] = FutureWarning) -> Iterator[N

Parameters
----------
category : `Warning` or subclass
category : `Warning`
The category of warning to suppress.
"""
with warnings.catch_warnings():
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/utils/inheritDoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ class and extend it with any additional documentation defined.

Parameters
----------
klass : object
klass : `type`
The class to inherit documentation from.

Returns
-------
decorator : callable
decorator : `~collections.abc.Callable`
Intermediate decorator used in the documentation process.

Notes
Expand Down
61 changes: 32 additions & 29 deletions python/lsst/utils/iteration.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ def chunk_iterable(data: Iterable[Any], chunk_size: int = 1_000) -> Iterator[tup

Parameters
----------
data : iterable of anything
data : `~collections.abc.Iterable` [ `typing.Any` ] of anything
The iterable to be chunked. Can be a mapping, in which case
the keys are returned in chunks.
chunk_size : int, optional
chunk_size : `int`, optional
The largest chunk to return. Can be smaller and depends on the
number of elements in the iterator. Defaults to 1_000.

Expand Down Expand Up @@ -58,7 +58,7 @@ def ensure_iterable(a: Any) -> Iterable[Any]:

Parameters
----------
a : iterable or `str` or not iterable
a : `~collections.abc.Iterable` or `str` or not iterable
Argument to be converted to an iterable.

Returns
Expand Down Expand Up @@ -115,18 +115,19 @@ def _extract_numeric_suffix(s: str) -> tuple[str, int | None]:
Returns the prefix and the numeric suffix as an integer, if present.

For example:
'node1' -> ('node', 1)
'node' -> ('node', None)
'node123abc' -> ('node123abc', None)

'node1' -> ('node', 1)
'node' -> ('node', None)
'node123abc' -> ('node123abc', None)

Parameters
----------
s : str
s : `str`
The string to extract the numeric suffix from.

Returns
-------
suffix : str
suffix : `str`
The numeric suffix of the string, if any.
"""
index = len(s)
Expand All @@ -151,13 +152,13 @@ def _add_pair_to_name(val_name: list[str], val0: int | str, val1: int | str, str

Parameters
----------
val_name : List[str]
val_name : `list` [ `str` ]
The list to append the formatted string to.
val0 : [int, str]
val0 : `int` or `str`
The starting value of the sequence.
val1 : [int, str]
val1 : `int` or `str`
The ending value of the sequence.
stride : int, optional
stride : `int`, optional
The stride or difference between consecutive numbers in the
sequence. Defaults to 1.
"""
Expand Down Expand Up @@ -195,12 +196,12 @@ def _is_list_of_ints(values: list[int | str]) -> TypeGuard[list[int]]:

Parameters
----------
values : List[int, str]:
values : `list` [`int` or `str`]:
The list of values to check.

Returns
-------
is_ints : bool
is_ints : `bool`
True if all values are integers, False otherwise.
"""
return all(isinstance(v, int) for v in values)
Expand All @@ -217,31 +218,33 @@ def sequence_to_string(values: list[int | str]) -> str:
strings with common prefixes are handled to produce a concise
representation.

>>> getNameOfSet([1, 2, 3, 5, 7, 8, 9])
'1..3^5^7..9'
>>> getNameOfSet(["node1", "node2", "node3"])
'node1..node3'
>>> getNameOfSet([10, 20, 30, 40])
'10..40:10'

Parameters
----------
values : list[int, str]:
values : `list` [ `int` or `str` ]
A list of items to be compacted. Must all be of the same type.

Returns
-------
sequence_as_string : str
sequence_as_string : `str`
A compact string representation of the input list.

Notes
-----
- The function handles both integers and strings.
- For strings with common prefixes, only the differing suffixes are
considered.
- The stride is determined as the minimum difference between
consecutive numbers.
- Strings without common prefixes are listed individually.
- The function handles both integers and strings.
- For strings with common prefixes, only the differing suffixes are
considered.
- The stride is determined as the minimum difference between
consecutive numbers.
- Strings without common prefixes are listed individually.

Examples
--------
>>> getNameOfSet([1, 2, 3, 5, 7, 8, 9])
'1..3^5^7..9'
>>> getNameOfSet(["node1", "node2", "node3"])
'node1..node3'
>>> getNameOfSet([10, 20, 30, 40])
'10..40:10'
"""
if not values:
return ""
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/utils/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def verbose(self, fmt: str, *args: Any, **kwargs: Any) -> None:
*args : `~typing.Any`
Parameters references by log message.
**kwargs : `~typing.Any`
Parameters forwarded to `log`.
Parameters forwarded to underlying logger.
"""
# There is no other way to achieve this other than a special logger
# method.
Expand All @@ -294,7 +294,7 @@ def trace(self, fmt: str, *args: Any, **kwargs: Any) -> None:
*args : `~typing.Any`
Parameters references by log message.
**kwargs : `~typing.Any`
Parameters forwarded to `log`.
Parameters forwarded to underlying logger.
"""
# There is no other way to achieve this other than a special logger
# method.
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/utils/timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def logInfo(
Name prefix, the resulting entries are ``CpuTime``, etc.. For example
`timeMethod` uses ``prefix = Start`` when the method begins and
``prefix = End`` when the method ends.
logLevel : optional
logLevel : `int`, optional
Log level (a `logging` level constant, such as `logging.DEBUG`).
metadata : `collections.abc.MutableMapping`, optional
Metadata object to write entries to, overriding ``obj.metadata``.
Expand Down Expand Up @@ -399,7 +399,7 @@ def time_this(
Prefix to use to prepend to the supplied logger to
create a new logger to use instead. No prefix is used if the value
is set to `None`. Defaults to "timer".
args : iterable of any
args : `~collections.abc.Iterable` [ `typing.Any` ]
Additional parameters passed to the log command that should be
written to ``msg``.
kwargs : `dict`, optional
Expand Down
8 changes: 4 additions & 4 deletions python/lsst/utils/wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class TemplateMeta(type):
classes with multiple template parameters) are good choices. Alternate
type keys for existing classes can be added by calling ``alias``, but only
after a subclass already been registered with a "primary" type key. For
example::
example:

.. code-block:: python

Expand All @@ -210,7 +210,7 @@ class Image(metaclass=TemplateMeta):

This allows user code to construct objects directly using ``Image``, as
long as an extra ``dtype`` keyword argument is passed that matches one of
the type keys::
the type keys:

.. code-block:: python

Expand All @@ -233,7 +233,7 @@ class Image(metaclass=TemplateMeta):
As an aid for those writing the Python wrappers for C++ classes,
``TemplateMeta`` also provides a way to add pure-Python methods and other
attributes to the wrapped template classes. To add a ``sum`` method to
all registered types, for example, we can just do::
all registered types, for example, we can just do:

.. code-block:: python

Expand All @@ -259,7 +259,7 @@ def sum(self):

Finally, abstract base classes that use ``TemplateMeta`` define a dict-
like interface for accessing their registered subclasses, providing
something like the C++ syntax for templates::
something like the C++ syntax for templates:

.. code-block:: python

Expand Down
4 changes: 4 additions & 0 deletions ups/utils.table
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
# deprecation period.
setupRequired(sconsUtils)

# Add this for convenience in testing documentation builds, even if the
# utils code does not yet use it directly during code builds.
setupRequired(sphinxutils)

envPrepend(PYTHONPATH, ${PRODUCT_DIR}/python)
Loading