From e1297243a6b3b22f78a1757b35ac7bd43a489ff6 Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Wed, 25 May 2022 11:29:57 -0400 Subject: [PATCH] updating docs (#139) --- README.md | 21 ++++++++------------- docs/_my_sigs.py | 37 +++++++++++++++++++++++++++++++++++++ docs/requirements.txt | 6 +++--- docs/source/conf.py | 3 ++- docs/source/index.rst | 6 ++++++ docs/source/ome_types.rst | 23 ++--------------------- docs/source/usage.rst | 17 ++++++++++++++++- src/ome_autogen.py | 9 ++++++--- src/ome_types/__init__.py | 10 +++++----- 9 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 docs/_my_sigs.py diff --git a/README.md b/README.md index ac84e6c0..6c33eade 100644 --- a/README.md +++ b/README.md @@ -229,11 +229,12 @@ As an example, the model will be rendered as the following dataclass in `ome_types/model/image.py` ```python -from dataclasses import field from datetime import datetime from typing import List, Optional -from ome_types.dataclasses import AUTO_SEQUENCE, ome_dataclass +from pydantic import Field + +from ome_types._base_type import OMEType from .annotation_ref import AnnotationRef from .experiment_ref import ExperimentRef @@ -249,29 +250,23 @@ from .simple_types import ImageID from .stage_label import StageLabel -@ome_dataclass -class Image: - """This element describes the actual image and its meta-data. - - - """ - +class Image(OMEType): + id: ImageID pixels: Pixels acquisition_date: Optional[datetime] = None - annotation_ref: List[AnnotationRef] = field(default_factory=list) + annotation_ref: List[AnnotationRef] = Field(default_factory=list) description: Optional[str] = None experiment_ref: Optional[ExperimentRef] = None experimenter_group_ref: Optional[ExperimenterGroupRef] = None experimenter_ref: Optional[ExperimenterRef] = None - id: ImageID = AUTO_SEQUENCE # type: ignore imaging_environment: Optional[ImagingEnvironment] = None instrument_ref: Optional[InstrumentRef] = None - microbeam_manipulation_ref: List[MicrobeamManipulationRef] = field( + microbeam_manipulation_ref: List[MicrobeamManipulationRef] = Field( default_factory=list ) name: Optional[str] = None objective_settings: Optional[ObjectiveSettings] = None - roi_ref: List[ROIRef] = field(default_factory=list) + roi_ref: List[ROIRef] = Field(default_factory=list) stage_label: Optional[StageLabel] = None ``` diff --git a/docs/_my_sigs.py b/docs/_my_sigs.py new file mode 100644 index 00000000..15896568 --- /dev/null +++ b/docs/_my_sigs.py @@ -0,0 +1,37 @@ +import inspect +from typing import Any, Dict, Optional, Tuple + +from pydantic import BaseModel +from sphinx.application import Sphinx +from sphinx.ext.autodoc import Options + + +def process_signature( + app: Sphinx, + what: str, + name: str, + obj: Any, + options: Options, + signature: str, + return_annotation: str, +) -> Optional[Tuple[str, None]]: + # just use names for pydantic signatures. Type hints will be in params + if isinstance(obj, type) and issubclass(obj, BaseModel): + s = inspect.signature(obj) + s = s.replace( + parameters=[p.replace(annotation=p.empty) for p in s.parameters.values()] + ) + return (str(s), None) + return None + + +def setup(app: Sphinx) -> Dict[str, bool]: + app.add_config_value("always_document_param_types", False, "html") + app.add_config_value("typehints_fully_qualified", False, "env") + app.add_config_value("typehints_document_rtype", True, "env") + app.add_config_value("typehints_use_rtype", True, "env") + app.add_config_value("typehints_defaults", None, "env") + app.add_config_value("simplify_optional_unions", True, "env") + app.add_config_value("typehints_formatter", None, "env") + app.connect("autodoc-process-signature", process_signature) + return {"parallel_read_safe": True} diff --git a/docs/requirements.txt b/docs/requirements.txt index 8961ba6b..bbfb343e 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,7 +1,7 @@ -sphinx==3.1.1 +sphinx==4.5.0 pygments -sphinx-rtd-theme==0.5.0 -sphinx-autodoc-typehints +sphinx-rtd-theme==1.0.0 +# sphinx-autodoc-typehints ipython==7.16.3 isort>=5.0 black diff --git a/docs/source/conf.py b/docs/source/conf.py index 411c0427..fa069f5f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,6 +16,7 @@ sys.path.insert(0, os.path.abspath("../../src")) from ome_types import __version__ # isort:skip # noqa + # -- Project information ----------------------------------------------------- project = "ome-types" @@ -37,7 +38,7 @@ 'sphinx.ext.viewcode', 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', - 'sphinx_autodoc_typehints', + 'docs._my_sigs', 'sphinx.ext.autosummary', 'sphinx.ext.intersphinx', 'IPython.sphinxext.ipython_directive', diff --git a/docs/source/index.rst b/docs/source/index.rst index 7dc3960e..8c0ee813 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,6 +8,12 @@ It converts the `ome.xsd schema `_ into a set of python types. +For a basic example on using the library to parse or write OME metadata, +see :doc:`usage`. For details on the attributes of each type, see the :doc:`api`. + +The best place to start in the API is the :class:`~ome_types.model.OME` class. +It is the root model object that ultimately contains all the data. Follow +the links in the parameters to learn more about each sub-field. .. toctree:: :maxdepth: 3 diff --git a/docs/source/ome_types.rst b/docs/source/ome_types.rst index 0098db94..8c64e4cd 100644 --- a/docs/source/ome_types.rst +++ b/docs/source/ome_types.rst @@ -1,25 +1,6 @@ ome\_types ========== -ome\_types.util ---------------- - -.. automodule:: ome_types.util - :members: - -ome\_types.schema ------------------ - -.. automodule:: ome_types.schema - :members: - -ome\_types.dataclasses ----------------------- - -.. automodule:: ome_types.dataclasses +.. automodule:: ome_types :members: - -ome\_types ----------- - -.. autofunction:: ome_types.from_xml + :noindex: OME diff --git a/docs/source/usage.rst b/docs/source/usage.rst index 0bf605dc..750b33e1 100644 --- a/docs/source/usage.rst +++ b/docs/source/usage.rst @@ -10,12 +10,21 @@ For example, you can parse an ome.xml, and then explore it with pythonic ``camel_case`` syntax and readable object representations: +Reading +------- + .. code-block:: python In [1]: from ome_types import from_xml In [2]: ome = from_xml('testing/data/hcs.ome.xml') +Note that :func:`~ome_types._convenience.from_xml` returns an instance of +:class:`~ome_types.model.OME`, This object is a container for all information +objects accessible by OME. + +.. code-block:: python + In [3]: ome Out[3]: OME( @@ -84,7 +93,10 @@ For example, you can parse an ome.xml, and then explore it with pythonic In [8]: ome.images[0].pixels.channels[0].emission_wavelength Out[8]: 523.0 -Then you might want to make some changes: +Modifying or Creating +--------------------- + +The ``OME`` object is mutable, and you may changes: .. code-block:: python @@ -140,6 +152,9 @@ And add elements by constructing new OME model objects: objectives=[<1 Objectives>], )] +Exporting +--------- + Finally, you can generate the OME-XML representation of the OME model object, for writing to a standalone .ome.xml file or inserting into the header of an OME-TIFF file: diff --git a/src/ome_autogen.py b/src/ome_autogen.py index 0c39f1ba..beef7a62 100644 --- a/src/ome_autogen.py +++ b/src/ome_autogen.py @@ -249,16 +249,16 @@ def __setstate__(self: Any, state: Dict[str, Any]) -> None: @classmethod def from_xml(cls, xml: Union[Path, str]) -> 'OME': - from ome_types._convenience import from_xml + from ome_types import from_xml return from_xml(xml) @classmethod def from_tiff(cls, path: Union[Path, str]) -> 'OME': - from ome_types._convenience import from_tiff + from ome_types import from_tiff return from_tiff(path) def to_xml(self) -> str: - from ome_types.schema import to_xml + from ome_types import to_xml return to_xml(self) """, ), @@ -434,6 +434,9 @@ def get_docstring( ) -> str: try: doc = dedent(component.annotation.documentation[0].text).strip() + # some docstrings include a start ('*Word') which makes sphinx angry + # this line wraps those in backticks + doc = re.sub(r"(\*\w+)\s", r"`\1` ", doc) # make sure the first line is followed by a double newline # and preserve paragraphs if summary: diff --git a/src/ome_types/__init__.py b/src/ome_types/__init__.py index 66013337..d1dc8541 100644 --- a/src/ome_types/__init__.py +++ b/src/ome_types/__init__.py @@ -25,14 +25,14 @@ ) __all__ = [ - "to_dict", - "validate_xml", - "from_xml", - "to_xml", "from_tiff", - "OME", + "from_xml", "model", + "OME", + "to_dict", + "to_xml", "ureg", + "validate_xml", ]