Skip to content

Commit 9ceafab

Browse files
authored
Migrate attribute comments to docstrings (#3639)
* Migrate attribute comments to docstrings * Minor fixes * Update AGENTS.md * Remove leading enwlines
1 parent 2dfe398 commit 9ceafab

17 files changed

Lines changed: 288 additions & 185 deletions

File tree

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- Keep primary/public functions before local helper functions in a module section.
2121
- Keep private classes, exceptions, and similar implementation-specific types close to the private functions that use them unless they are shared more broadly in the module.
2222
- Prefer pydantic-style models in `core/models`.
23+
- Document attributes when the note adds behavior, compatibility, or semantic context that is not obvious from the name and type. Use attribute docstrings without leading newline.
2324
- Tests use `test_*.py` modules and `test_*` functions; fixtures live near usage.
2425

2526
## Testing Guidelines

src/dstack/_internal/core/models/backends/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@ class BackendType(str, enum.Enum):
3232
CLOUDRIFT = "cloudrift"
3333
CRUSOE = "crusoe"
3434
CUDO = "cudo"
35-
DATACRUNCH = "datacrunch" # BackendType for backward compatibility
35+
DATACRUNCH = "datacrunch"
36+
"""`DATACRUNCH` is kept as a `BackendType` for backward compatibility."""
3637
DIGITALOCEAN = "digitalocean"
3738
DSTACK = "dstack"
3839
GCP = "gcp"
3940
HOTAISLE = "hotaisle"
4041
KUBERNETES = "kubernetes"
4142
LAMBDA = "lambda"
4243
LOCAL = "local"
43-
REMOTE = "remote" # TODO: replace for LOCAL
44+
REMOTE = "remote"
4445
NEBIUS = "nebius"
4546
OCI = "oci"
4647
RUNPOD = "runpod"

src/dstack/_internal/core/models/common.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,10 @@ class RegistryAuth(FrozenCoreModel):
134134

135135

136136
class ApplyAction(str, Enum):
137-
CREATE = "create" # resource is to be created or overridden
138-
UPDATE = "update" # resource is to be updated in-place
137+
CREATE = "create"
138+
"""`CREATE` means the resource is to be created or overridden."""
139+
UPDATE = "update"
140+
"""`UPDATE` means the resource is to be updated in-place."""
139141

140142

141143
class NetworkMode(str, Enum):

src/dstack/_internal/core/models/compute_groups.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ class ComputeGroupProvisioningData(CoreModel):
2424
compute_group_id: str
2525
compute_group_name: str
2626
backend: BackendType
27-
# In case backend provisions instance in another backend,
28-
# it may set that backend as base_backend.
2927
base_backend: Optional[BackendType] = None
28+
"""`base_backend` may be set when a backend provisions an instance in another backend and needs
29+
to record that backend as `base_backend`.
30+
"""
3031
region: str
3132
job_provisioning_datas: List[JobProvisioningData]
32-
backend_data: Optional[str] = None # backend-specific data in json
33+
backend_data: Optional[str] = None
34+
"""`backend_data` stores backend-specific data in JSON."""
3335

3436

3537
class ComputeGroup(CoreModel):

src/dstack/_internal/core/models/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class RepoConfig(CoreModel):
2323

2424
class GlobalConfig(CoreModel):
2525
projects: Annotated[List[ProjectConfig], Field(description="The list of projects")] = []
26-
# Not used since 0.20.0. Can be removed when most users update their `config.yml` (it's updated
27-
# each time a project is added)
2826
repos: Annotated[list[RepoConfig], Field(exclude=True)] = []
27+
"""`repos` is not used since 0.20.0. It can be removed when most users update their `config.yml`
28+
because it is updated each time a project is added.
29+
"""

src/dstack/_internal/core/models/configurations.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,10 @@ def parse(cls, v: str) -> "PortMapping":
101101

102102

103103
class RepoExistsAction(str, Enum):
104-
# Don't try to check out, terminate the run with an error (the default action since 0.20.0)
105104
ERROR = "error"
106-
# Don't try to check out, skip the repo (the logic hardcoded in the pre-0.20.0 runner)
105+
"""`ERROR` means do not try to check out and terminate the run with an error. This is the default action since 0.20.0."""
107106
SKIP = "skip"
107+
"""`SKIP` means do not try to check out and skip the repo. This is the logic hardcoded in the pre-0.20.0 runner."""
108108

109109

110110
class RepoSpec(CoreModel):
@@ -469,8 +469,8 @@ class BaseRunConfiguration(CoreModel):
469469
),
470470
),
471471
] = None
472-
# deprecated since 0.18.31; has no effect
473472
home_dir: str = "/root"
473+
"""`home_dir` is deprecated since 0.18.31 and has no effect."""
474474
registry_auth: Annotated[
475475
Optional[RegistryAuth], Field(description="Credentials for pulling a private Docker image")
476476
] = None
@@ -540,8 +540,11 @@ class BaseRunConfiguration(CoreModel):
540540
list[FilePathMapping],
541541
Field(description="The local to container file path mappings"),
542542
] = []
543-
# deprecated since 0.18.31; task, service -- no effect; dev-environment -- executed right before `init`
544543
setup: CommandsList = []
544+
"""
545+
setup: Deprecated since 0.18.31. It has no effect for tasks and services; for
546+
dev environments it runs right before `init`.
547+
"""
545548

546549
@validator("python", pre=True, always=True)
547550
def convert_python(cls, v, values) -> Optional[PythonVersion]:

src/dstack/_internal/core/models/fleets.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131

3232
class FleetStatus(str, Enum):
33-
# Currently all fleets are ACTIVE/TERMINATING/TERMINATED
34-
# SUBMITTED/FAILED may be used if fleets require async processing
33+
# Currently all fleets are ACTIVE, TERMINATING, or TERMINATED.
34+
# SUBMITTED and FAILED may be used if fleets require async processing.
3535
SUBMITTED = "submitted"
3636
ACTIVE = "active"
3737
TERMINATING = "terminating"
@@ -372,10 +372,11 @@ class FleetSpec(generate_dual_core_model(FleetSpecConfig)):
372372
configuration_path: Optional[str] = None
373373
profile: Profile
374374
autocreated: bool = False
375-
# merged_profile stores profile parameters merged from profile and configuration.
376-
# Read profile parameters from merged_profile instead of profile directly.
377-
# TODO: make merged_profile a computed field after migrating to pydanticV2
375+
# TODO: make `merged_profile` a computed field after migrating to Pydantic v2.
378376
merged_profile: Annotated[Profile, Field(exclude=True)] = None
377+
"""`merged_profile` stores profile parameters merged from `profile` and `configuration`.
378+
Read profile parameters from `merged_profile` instead of `profile` directly.
379+
"""
379380

380381
@root_validator
381382
def _merged_profile(cls, values) -> Dict:
@@ -416,7 +417,8 @@ class FleetPlan(CoreModel):
416417
offers: List[InstanceOfferWithAvailability]
417418
total_offers: int
418419
max_offer_price: Optional[float] = None
419-
action: Optional[ApplyAction] = None # default value for backward compatibility
420+
action: Optional[ApplyAction] = None
421+
"""`action` uses a default value for backward compatibility."""
420422

421423
def get_effective_spec(self) -> FleetSpec:
422424
if self.effective_spec is not None:

src/dstack/_internal/core/models/gateways.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,33 @@ class GatewaySpec(CoreModel):
102102

103103

104104
class Gateway(CoreModel):
105-
# ID is only optional on the client side for compatibility with pre-0.20.7 servers.
106-
# TODO(0.21): Make required.
105+
# TODO(0.21): Make `id` required.
107106
id: Optional[uuid.UUID] = None
107+
"""`id` is only optional on the client side for compatibility with pre-0.20.7 servers."""
108108
name: str
109109
configuration: GatewayConfiguration
110110
created_at: datetime.datetime
111111
status: GatewayStatus
112112
status_message: Optional[str]
113-
# The ip address / hostname the user should set up the domain for.
114-
# Could be the same as ip_address but also different, e.g. gateway behind ALB.
115113
hostname: Optional[str]
116-
# The ip address of the gateway instance
114+
"""`hostname` is the IP address or hostname the user should set up the domain for.
115+
Could be the same as `ip_address` but also different, for example a gateway behind ALB.
116+
"""
117117
ip_address: Optional[str]
118+
"""`ip_address` is the IP address of the gateway instance."""
118119
instance_id: Optional[str]
119120
wildcard_domain: Optional[str]
120121
default: bool
121-
# TODO: Deprecated configuration fields duplicated on top-level
122-
# for backward compatibility with 0.19.x clients that expect them required.
123-
# Remove after 0.21
124122
backend: Optional[BackendType] = None
123+
"""`backend` duplicates a configuration field on the top level for backward compatibility
124+
with 0.19.x clients that expect it to be required.
125+
Remove after 0.21.
126+
"""
125127
region: Optional[str] = None
128+
"""`region` duplicates a configuration field on the top level for backward compatibility
129+
with 0.19.x clients that expect it to be required.
130+
Remove after 0.21.
131+
"""
126132

127133

128134
class GatewayPlan(CoreModel):
@@ -147,8 +153,10 @@ class GatewayComputeConfiguration(CoreModel):
147153

148154
class GatewayProvisioningData(CoreModel):
149155
instance_id: str
150-
ip_address: str # TODO: rename, Kubernetes uses domain names
156+
# TODO: rename `ip_address`; Kubernetes uses domain names here.
157+
ip_address: str
151158
region: str
152159
availability_zone: Optional[str] = None
153160
hostname: Optional[str] = None
154-
backend_data: Optional[str] = None # backend-specific data in json
161+
backend_data: Optional[str] = None
162+
"""`backend_data` stores backend-specific data in JSON."""

src/dstack/_internal/core/models/instances.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
class Gpu(CoreModel):
2424
name: str
2525
memory_mib: int
26-
# Although it's declared as Optional, in fact it always has a value set by the root validator,
27-
# that is, `assert gpu.vendor is not None` should be a safe type narrowing.
2826
vendor: Optional[gpuhunt.AcceleratorVendor] = None
27+
"""`vendor` is declared as optional, but the root validator always sets a value.
28+
`assert gpu.vendor is not None` should be a safe type narrowing.
29+
"""
2930

3031
@root_validator(pre=True)
3132
def validate_name_and_vendor(cls, values):
@@ -54,13 +55,15 @@ class Resources(CoreModel):
5455
memory_mib: int
5556
gpus: List[Gpu]
5657
spot: bool
57-
disk: Disk = Disk(size_mib=102400) # the default value (100GB) for backward compatibility
58+
disk: Disk = Disk(size_mib=102400)
59+
"""`disk` defaults to 100GB for backward compatibility."""
5860
cpu_arch: Optional[gpuhunt.CPUArchitecture] = None
59-
# Deprecated: description is now generated client-side. TODO: remove in 0.21.
61+
# TODO: remove `description` in 0.21.
6062
description: Annotated[
6163
str,
6264
Field(description="Deprecated: generated client-side. Will be removed in 0.21."),
6365
] = ""
66+
"""`description` is deprecated because it is now generated client-side."""
6467

6568
@root_validator
6669
def _description(cls, values) -> Dict:
@@ -187,7 +190,8 @@ class RemoteConnectionInfo(CoreModel):
187190
class InstanceConfiguration(CoreModel):
188191
project_name: str
189192
instance_name: str
190-
user: str # dstack user name
193+
user: str
194+
"""`user` stores the dstack user name."""
191195
ssh_keys: List[SSHKey]
192196
instance_id: Optional[str] = None
193197
reservation: Optional[str] = None
@@ -208,7 +212,8 @@ class InstanceAvailability(Enum):
208212
AVAILABLE = "available"
209213
NOT_AVAILABLE = "not_available"
210214
NO_QUOTA = "no_quota"
211-
NO_BALANCE = "no_balance" # For dstack Sky
215+
NO_BALANCE = "no_balance"
216+
"""`NO_BALANCE` is used for dstack Sky."""
212217
IDLE = "idle"
213218
BUSY = "busy"
214219

@@ -268,7 +273,8 @@ class InstanceTerminationReason(str, Enum):
268273
NO_OFFERS = "no_offers"
269274
MASTER_FAILED = "master_failed"
270275
MAX_INSTANCES_LIMIT = "max_instances_limit"
271-
NO_BALANCE = "no_balance" # used in dstack Sky
276+
NO_BALANCE = "no_balance"
277+
"""`NO_BALANCE` is used in dstack Sky."""
272278

273279
@classmethod
274280
def from_legacy_str(cls, v: str) -> "InstanceTerminationReason":
@@ -332,14 +338,16 @@ class Instance(CoreModel):
332338
fleet_id: Optional[UUID] = None
333339
fleet_name: Optional[str] = None
334340
instance_num: int
335-
job_name: Optional[str] = None # deprecated, always None (instance can have more than one job)
341+
job_name: Optional[str] = None
342+
"""`job_name` is deprecated and always `None` because an instance can have more than one job."""
336343
hostname: Optional[str] = None
337344
status: InstanceStatus
338345
unreachable: bool = False
339346
health_status: HealthStatus = HealthStatus.HEALTHY
340-
# termination_reason stores InstanceTerminationReason.
341-
# str allows adding new enum members without breaking compatibility with old clients.
342347
termination_reason: Optional[str] = None
348+
"""`termination_reason` stores `InstanceTerminationReason`.
349+
`str` allows adding new enum members without breaking compatibility with old clients.
350+
"""
343351
termination_reason_message: Optional[str] = None
344352
created: datetime.datetime
345353
finished_at: Optional[datetime.datetime] = None

src/dstack/_internal/core/models/placement.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class PlacementGroupConfiguration(CoreModel):
1616

1717

1818
class PlacementGroupProvisioningData(CoreModel):
19-
backend: BackendType # can be different from configuration backend
19+
backend: BackendType
20+
"""`backend` can be different from the backend in `configuration`."""
2021
backend_data: Optional[str] = None
2122

2223

0 commit comments

Comments
 (0)