Skip to content

Commit 97bbe0d

Browse files
mhusbynflowclaude
andcommitted
docs(samples): use autodoc_pydantic for Pydantic model docs
Replaces autoclass with autopydantic_model directives so that model fields render with their type, description, and required status in a single entry — instead of the previous duplicated Parameters/Fields sections and the misleading (**data) signature. Field descriptions are moved from :param: docstrings into Field(description=...) so autodoc_pydantic can pick them up directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1e75e67 commit 97bbe0d

3 files changed

Lines changed: 42 additions & 63 deletions

File tree

flowbio/v2/samples.py

Lines changed: 27 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from pathlib import Path
3232
from typing import TYPE_CHECKING
3333

34-
from pydantic import BaseModel
34+
from pydantic import BaseModel, Field
3535
from tqdm import tqdm
3636

3737
from flowbio.v2._pagination import PageIterator
@@ -45,35 +45,22 @@
4545
class SampleType(BaseModel, frozen=True):
4646
"""A type of sample that can be uploaded to the Flow platform.
4747
48-
:param identifier: Unique identifier for this sample type.
49-
:param name: Human-readable display name.
50-
:param description: Explanation of what this sample type represents.
51-
5248
Example::
5349
5450
sample_types = client.samples.get_types()
5551
for st in sample_types:
5652
print(f"{st.identifier}: {st.name}")
5753
"""
5854

59-
identifier: str
60-
name: str
61-
description: str
55+
identifier: str = Field(description="Unique identifier for this sample type.")
56+
name: str = Field(description="Human-readable display name.")
57+
description: str = Field(description="Explanation of what this sample type represents.")
6258

6359

6460
class MetadataAttribute(BaseModel, frozen=True):
6561
"""A metadata attribute that can be attached to a sample. See :ref:`metadata-attributes` for a more detailed
6662
explanation.
6763
68-
:param identifier: Unique identifier for this attribute.
69-
:param name: Human-readable display name.
70-
:param description: Explanation of what this attribute represents.
71-
:param required: Whether this attribute is required at sample creation.
72-
:param required_for_sample_types: Sample type identifiers for which
73-
this attribute is required at creation.
74-
:param options: The list of valid values, or ``None`` if any value
75-
is accepted.
76-
7764
Example::
7865
7966
attributes = client.samples.get_metadata_attributes()
@@ -82,75 +69,64 @@ class MetadataAttribute(BaseModel, frozen=True):
8269
print(f"{attr.name}: choose from {attr.options}")
8370
"""
8471

85-
identifier: str
86-
name: str
87-
description: str
88-
required: bool
89-
required_for_sample_types: list[str]
90-
options: list[str] | None
72+
identifier: str = Field(description="Unique identifier for this attribute.")
73+
name: str = Field(description="Human-readable display name.")
74+
description: str = Field(description="Explanation of what this attribute represents.")
75+
required: bool = Field(description="Whether this attribute is required at sample creation.")
76+
required_for_sample_types: list[str] = Field(
77+
description="Sample type identifiers for which this attribute is required at creation.",
78+
)
79+
options: list[str] | None = Field(
80+
description="The list of valid values, or ``None`` if any value is accepted.",
81+
)
9182

9283

9384
class Project(BaseModel, frozen=True):
9485
"""A project that samples can be assigned to.
9586
96-
:param id: Unique identifier for this project.
97-
:param name: Human-readable display name.
98-
:param description: Explanation of what this project is for.
99-
10087
Example::
10188
10289
projects = client.samples.get_owned_projects()
10390
for p in projects:
10491
print(f"{p.id}: {p.name}")
10592
"""
10693

107-
id: str
108-
name: str
109-
description: str
94+
id: str = Field(description="Unique identifier for this project.")
95+
name: str = Field(description="Human-readable display name.")
96+
description: str = Field(description="Explanation of what this project is for.")
11097

11198

11299
class Organism(BaseModel, frozen=True):
113100
"""An organism that a sample can be associated with.
114101
115-
:param id: Unique identifier for this organism.
116-
:param name: Common name.
117-
:param latin_name: Scientific (Latin) name.
118-
119102
Example::
120103
121104
organisms = client.samples.get_organisms()
122105
for o in organisms:
123106
print(f"{o.id}: {o.name} ({o.latin_name})")
124107
"""
125108

126-
id: str
127-
name: str
128-
latin_name: str
109+
id: str = Field(description="Unique identifier for this organism.")
110+
name: str = Field(description="Common name.")
111+
latin_name: str = Field(description="Scientific (Latin) name.")
129112

130113

131114
class Sample(BaseModel, frozen=True):
132115
"""A sample on the Flow platform. For now this only includes id, but when we
133116
add more methods to retrieve samples with more detail, more fields will be added.
134-
135-
136-
:param id: The unique identifier of the sample.
137117
"""
138118

139-
id: str
119+
id: str = Field(description="The unique identifier of the sample.")
140120

141121

142122
class MultiplexedUpload(BaseModel, frozen=True):
143-
"""Result of a multiplexed data upload.
123+
"""Result of a multiplexed data upload."""
144124

145-
:param data_ids: IDs for the uploaded multiplexed reads data.
146-
:param annotation_id: ID for the uploaded annotation data.
147-
:param warnings: Annotation warnings returned by the server.
148-
Empty if the annotation was accepted without warnings.
149-
"""
150-
151-
data_ids: list[str]
152-
annotation_id: str
153-
warnings: list[dict]
125+
data_ids: list[str] = Field(description="IDs for the uploaded multiplexed reads data.")
126+
annotation_id: str = Field(description="ID for the uploaded annotation data.")
127+
warnings: list[dict] = Field(
128+
description="Annotation warnings returned by the server. Empty if the annotation was accepted without warnings.",
129+
)
154130

155131

156132
class SampleResource:

source/conf.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,17 @@
2121
"sphinx.ext.autodoc",
2222
"sphinx.ext.intersphinx",
2323
"sphinx_autodoc_typehints",
24+
"sphinxcontrib.autodoc_pydantic",
2425
]
2526

27+
autodoc_pydantic_model_hide_paramlist = True
28+
autodoc_pydantic_model_show_json = False
29+
autodoc_pydantic_model_show_config_summary = False
30+
autodoc_pydantic_model_show_validator_summary = False
31+
autodoc_pydantic_model_show_field_summary = False
32+
autodoc_pydantic_field_show_alias = False
33+
autodoc_pydantic_field_doc_policy = "description"
34+
2635
templates_path = ['_templates']
2736
exclude_patterns = []
2837

source/v2/samples.rst

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -175,20 +175,14 @@ API Reference
175175
Models
176176
------
177177

178-
.. autoclass:: flowbio.v2.samples.Sample
179-
:no-members:
178+
.. autopydantic_model:: flowbio.v2.samples.Sample
180179

181-
.. autoclass:: flowbio.v2.samples.SampleType
182-
:no-members:
180+
.. autopydantic_model:: flowbio.v2.samples.SampleType
183181

184-
.. autoclass:: flowbio.v2.samples.MetadataAttribute
185-
:no-members:
182+
.. autopydantic_model:: flowbio.v2.samples.MetadataAttribute
186183

187-
.. autoclass:: flowbio.v2.samples.Project
188-
:no-members:
184+
.. autopydantic_model:: flowbio.v2.samples.Project
189185

190-
.. autoclass:: flowbio.v2.samples.Organism
191-
:no-members:
186+
.. autopydantic_model:: flowbio.v2.samples.Organism
192187

193-
.. autoclass:: flowbio.v2.samples.MultiplexedUpload
194-
:no-members:
188+
.. autopydantic_model:: flowbio.v2.samples.MultiplexedUpload

0 commit comments

Comments
 (0)