Skip to content

Commit eeacdf5

Browse files
committed
feat (Configuration): add attribute docstrings and enable use_attribute_docstrings for the pydantic models
feat (Configuration): documenting other attributes fix: formatting and remove caching
1 parent c265a47 commit eeacdf5

File tree

1 file changed

+123
-6
lines changed

1 file changed

+123
-6
lines changed

diracx-core/src/diracx/core/config/schema.py

Lines changed: 123 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727

2828

2929
class BaseModel(_BaseModel):
30-
model_config = ConfigDict(extra="forbid", frozen=True)
30+
model_config = ConfigDict(
31+
extra="forbid", frozen=True, use_attribute_docstrings=True
32+
)
3133

3234
@model_validator(mode="before")
3335
@classmethod
@@ -68,35 +70,60 @@ def legacy_adaptor(cls, v):
6870

6971
class UserConfig(BaseModel):
7072
PreferedUsername: str
73+
"""Preferred username for the user account."""
7174
DNs: list[str] = []
75+
"""Distinguished Names of the user's certificates (Mandatory for certificate-based authentication)."""
7276
Email: EmailStr | None = None
77+
"""User e-mail address (Mandatory for user registration)."""
7378
Suspended: list[str] = []
79+
"""List of VOs where the user is suspended."""
7480
Quota: int | None = None
81+
"""Quota assigned to the user, expressed in MBs."""
7582
# TODO: These should be LHCbDIRAC specific
7683
CERNAccountType: str | None = None
84+
"""CERN account type (e.g. 'Primary', 'Secondary')."""
7785
PrimaryCERNAccount: str | None = None
86+
"""CERN account username."""
7887
CERNPersonId: int | None = None
79-
80-
# Mapping from VO name to affiliation end date (YYYY-MM-DD)
88+
"""CERN person ID."""
8189
AffiliationEnds: dict[str, date] = Field(default_factory=dict)
90+
"""Mapping from VO name to affiliation end date (YYYY-MM-DD)."""
8291

8392

8493
class GroupConfig(BaseModel):
8594
AutoAddVOMS: bool = False
95+
"""Controls automatic addition of VOMS extension when creating proxies."""
8696
AutoUploadPilotProxy: bool = False
97+
"""Controls automatic Proxy upload for Pilot groups."""
8798
AutoUploadProxy: bool = False
99+
"""Controls automatic Proxy upload for users in this group."""
88100
JobShare: int = 1000
101+
"""Share of computing resources allocated to this group for fair share scheduling."""
89102
Properties: SerializableSet[SecurityProperty]
103+
"""Group properties (set permissions of the group users).
104+
105+
Examples: NormalUser, GenericPilot, ServiceAdministrator.
106+
"""
90107
Quota: int | None = None
108+
"""Group-specific quota override."""
91109
Users: SerializableSet[str]
110+
"""DIRAC user logins that belong to this group."""
92111
AllowBackgroundTQs: bool = False
112+
"""Allow background Task Queues for this group."""
93113
VOMSRole: str | None = None
114+
"""Role of the users in the VO (e.g., '/lhcb' for LHCb VO)."""
94115
AutoSyncVOMS: bool = False
116+
"""Automatically synchronize group membership with VOMS server."""
95117

96118

97119
class IdpConfig(BaseModel):
98120
URL: str
121+
"""The authorization server's issuer identifier.
122+
123+
This is a URL that uses the 'https' scheme and has no query or fragment components.
124+
"""
99125
ClientID: str
126+
"""OAuth 2.0 client identifier received after client registration with the identity provider."""
100127

101128
@property
102129
def server_metadata_url(self):
@@ -105,25 +132,44 @@ def server_metadata_url(self):
105132

106133
class SupportInfo(BaseModel):
107134
Email: str | None = None
135+
"""Support contact email address."""
108136
Webpage: str | None = None
137+
"""Support webpage URL."""
109138
Message: str = "Please contact system administrator"
139+
"""Default support message displayed to users."""
110140

111141

112142
class RegistryConfig(BaseModel):
113143
IdP: IdpConfig
144+
"""Registered identity provider associated with this VO."""
114145
Support: SupportInfo = Field(default_factory=SupportInfo)
146+
"""Support contact information for this VO."""
115147
DefaultGroup: str
148+
"""Default user group to be used for new users in this VO."""
116149
DefaultStorageQuota: float = 0
150+
"""Default storage quota in GB for users in this VO."""
117151
DefaultProxyLifeTime: int = 12 * 60 * 60
152+
"""Default proxy time expressed in seconds (default: 43200 = 12 hours)."""
118153
VOMSName: str | None = None
154+
"""Real VOMS VO name, if this VO is associated with VOMS VO."""
119155

120156
Users: MutableMapping[str, UserConfig]
157+
"""DIRAC users section, subsections represent the name of the user."""
121158
Groups: MutableMapping[str, GroupConfig]
159+
"""DIRAC groups section, subsections represent the name of the group."""
122160

123161
def sub_from_preferred_username(self, preferred_username: str) -> str:
124162
"""Get the user sub from the preferred username.
125163
126-
TODO: This could easily be cached or optimised
164+
Args:
165+
preferred_username: The preferred username to look up.
166+
167+
Returns:
168+
The user sub (subject identifier) for the given username.
169+
170+
Raises:
171+
KeyError: If no user with the given preferred username is found.
172+
127173
"""
128174
for sub, user in self.Users.items():
129175
if user.PreferedUsername == preferred_username:
@@ -133,80 +179,135 @@ def sub_from_preferred_username(self, preferred_username: str) -> str:
133179

134180
class DIRACConfig(BaseModel):
135181
NoSetup: bool = False
182+
"""Flag to skip setup procedures during DIRAC initialization. Takes a boolean value. By default false."""
136183

137184

138185
class JobMonitoringConfig(BaseModel):
139186
GlobalJobsInfo: bool = True
187+
"""Enable global job information monitoring across all VOs."""
140188

141189

142190
class JobSchedulingConfig(BaseModel):
143191
EnableSharesCorrection: bool = False
192+
"""Enable correction of job shares based on historical usage."""
144193
MaxRescheduling: int = 3
194+
"""Maximum number of times a job can be rescheduled."""
145195

146196

147197
class ServicesConfig(BaseModel):
148198
Catalogs: MutableMapping[str, Any] | None = None
199+
"""Configuration for data catalog services."""
149200
JobMonitoring: JobMonitoringConfig = JobMonitoringConfig()
201+
"""Job monitoring service configuration."""
150202
JobScheduling: JobSchedulingConfig = JobSchedulingConfig()
203+
"""Job scheduling service configuration."""
151204

152205

153206
class JobDescriptionConfig(BaseModel):
154207
DefaultCPUTime: int = 86400
208+
"""Default CPU time limit for jobs in seconds (default: 24 hours)."""
155209
DefaultPriority: int = 1
210+
"""Default job priority."""
156211
MinCPUTime: int = 100
212+
"""Minimum allowed CPU time for jobs in seconds."""
157213
MinPriority: int = 0
214+
"""Minimum allowed job priority."""
158215
MaxCPUTime: int = 500000
216+
"""Maximum allowed CPU time for jobs in seconds."""
159217
MaxPriority: int = 10
218+
"""Maximum allowed job priority."""
160219
MaxInputData: int = 100
220+
"""Maximum number of input data files per job."""
161221
AllowedJobTypes: list[str] = ["User", "Test", "Hospital"]
222+
"""List of allowed job types."""
162223

163224

164225
class InputDataPolicyProtocolsConfig(BaseModel):
165226
Remote: list[str] = []
227+
"""List of protocols that should be considered as remote access methods (e.g., 'https', 'gsiftp', 'srm')."""
166228
Local: list[str] = []
229+
"""List of protocols that should be considered as local access methods (e.g., 'file', 'root')."""
167230

168231

169232
class InputDataPolicyConfig(BaseModel):
170233
# TODO: Remove this once the model is extended to support everything
171-
model_config = ConfigDict(extra="ignore", frozen=True)
234+
model_config = ConfigDict(
235+
extra="ignore", frozen=True, use_attribute_docstrings=True
236+
)
172237

173238
Default: str = "Default = DIRAC.WorkloadManagementSystem.Client.InputDataByProtocol"
239+
"""Default input data access policy. This is the fallback policy when no specific protocol is matched."""
174240
Download: str = "DIRAC.WorkloadManagementSystem.Client.DownloadInputData"
241+
"""Policy for downloading input data files to the local worker node before job execution."""
175242
Protocol: str = "DIRAC.WorkloadManagementSystem.Client.InputDataByProtocol"
243+
"""Policy for accessing input data directly via supported protocols without downloading."""
176244
AllReplicas: bool = True
245+
"""Whether to consider all available replicas when resolving input data locations."""
177246
Protocols: InputDataPolicyProtocolsConfig = InputDataPolicyProtocolsConfig()
247+
"""Protocol-specific configuration defining which protocols are available for remote and local access."""
178248
InputDataModule: str = "DIRAC.Core.Utilities.InputDataResolution"
249+
"""Module responsible for resolving input data locations and determining access methods."""
179250

180251

181252
class OperationsConfig(BaseModel):
182253
EnableSecurityLogging: bool = False
254+
"""Flag for globally disabling the use of the SecurityLogging service.
255+
256+
This is False by default, as should be migrated to use centralized logging.
257+
"""
183258
InputDataPolicy: InputDataPolicyConfig = InputDataPolicyConfig()
259+
"""Specify how jobs access their data. See InputDataResolution documentation for details."""
184260
JobDescription: JobDescriptionConfig = JobDescriptionConfig()
261+
"""Configuration for job description defaults and limits."""
185262
Services: ServicesConfig = ServicesConfig()
263+
"""Configuration for various DIRAC services."""
186264
SoftwareDistModule: str = "LocalSoftwareDist"
265+
"""Module used for software distribution."""
187266

188267
Cloud: MutableMapping[str, Any] | None = None
268+
"""Cloud computing configuration."""
189269
DataConsistency: MutableMapping[str, Any] | None = None
270+
"""Data consistency checking configuration."""
190271
DataManagement: MutableMapping[str, Any] | None = None
272+
"""Data management operations configuration."""
191273
EMail: MutableMapping[str, Any] | None = None
274+
"""Email notification configuration."""
192275
GaudiExecution: MutableMapping[str, Any] | None = None
276+
"""Gaudi framework execution configuration."""
193277
Hospital: MutableMapping[str, Any] | None = None
278+
"""Job recovery and hospital configuration."""
194279
JobScheduling: MutableMapping[str, Any] | None = None
280+
"""Advanced job scheduling configuration."""
195281
JobTypeMapping: MutableMapping[str, Any] | None = None
282+
"""Mapping of job types to execution environments."""
196283
LogFiles: MutableMapping[str, Any] | None = None
284+
"""Log file management configuration."""
197285
LogStorage: MutableMapping[str, Any] | None = None
286+
"""Log storage backend configuration."""
198287
Logging: MutableMapping[str, Any] | None = None
288+
"""General logging configuration."""
199289
Matching: MutableMapping[str, Any] | None = None
290+
"""Job matching configuration."""
200291
MonitoringBackends: MutableMapping[str, Any] | None = None
292+
"""Monitoring backend configuration."""
201293
NagiosConnector: MutableMapping[str, Any] | None = None
294+
"""Nagios monitoring integration configuration."""
202295
Pilot: MutableMapping[str, Any] | None = None
296+
"""Pilot job configuration."""
203297
Productions: MutableMapping[str, Any] | None = None
298+
"""Production management configuration."""
204299
Shares: MutableMapping[str, Any] | None = None
300+
"""Resource sharing configuration."""
205301
Shifter: MutableMapping[str, Any] | None = None
302+
"""Shifter proxy configuration."""
206303
SiteSEMappingByProtocol: MutableMapping[str, Any] | None = None
304+
"""Site storage element mapping by protocol."""
207305
TransformationPlugins: MutableMapping[str, Any] | None = None
306+
"""Data transformation plugin configuration."""
208307
Transformations: MutableMapping[str, Any] | None = None
308+
"""Data transformation system configuration."""
209309
ResourceStatus: MutableMapping[str, Any] | None = None
310+
"""Resource status monitoring configuration."""
210311

211312

212313
class ResourcesComputingConfig(BaseModel):
@@ -216,6 +317,10 @@ class ResourcesComputingConfig(BaseModel):
216317
# TODO: Figure out how to remove this in LHCbDIRAC and then consider
217318
# constraining there to be at least one entry
218319
OSCompatibility: MutableMapping[str, set[str]] = {}
320+
"""Compatibility matrix between DIRAC platforms and OS versions.
321+
322+
Used by SiteDirector to match TaskQueues to Computing Element capabilities.
323+
"""
219324

220325
@field_validator("OSCompatibility", mode="before")
221326
@classmethod
@@ -239,22 +344,34 @@ def ensure_self_compatibility(cls, v: dict[str, set[str]]) -> dict[str, set[str]
239344

240345
class ResourcesConfig(BaseModel):
241346
# TODO: Remove this once the model is extended to support everything
242-
model_config = ConfigDict(extra="ignore", frozen=True)
347+
model_config = ConfigDict(
348+
extra="ignore", frozen=True, use_attribute_docstrings=True
349+
)
243350

244351
Computing: ResourcesComputingConfig = ResourcesComputingConfig()
352+
"""Computing resource configuration."""
245353

246354

247355
class Config(BaseModel):
248356
DIRAC: DIRACConfig
357+
"""The DIRAC section contains general parameters needed in most installation types."""
249358
Operations: MutableMapping[str, OperationsConfig]
359+
"""Operations configuration per VO. The Defaults entry is automatically merged into each VO-specific config."""
250360
Registry: MutableMapping[str, RegistryConfig]
361+
"""Registry sections to register VOs, groups, users and hosts. See UserManagement documentation for details."""
251362
Resources: ResourcesConfig = ResourcesConfig()
363+
"""Resources configuration including computing elements, storage elements, and sites."""
252364

253365
LocalSite: Any = None
366+
"""Local site-specific configuration parameters."""
254367
LogLevel: Any = None
368+
"""Global logging level configuration."""
255369
MCTestingDestination: Any = None
370+
"""Monte Carlo testing destination configuration."""
256371
Systems: Any | None = None
372+
"""Systems configuration."""
257373
WebApp: Any = None
374+
"""Web application configuration parameters."""
258375

259376
@model_validator(mode="before")
260377
@classmethod

0 commit comments

Comments
 (0)