31
31
"IntoTag" ,
32
32
"MaybeTaggable" ,
33
33
"Taggable" ,
34
+ "Tag" ,
34
35
"as_tag" ,
35
36
"ids" ,
36
37
"is_active_endpoint" ,
@@ -147,6 +148,7 @@ def __len__(self) -> int:
147
148
return len (self .tag .attributes .get ("class" , "" ).split ())
148
149
149
150
def add (self , * classes : str ) -> tags .html_tag : # type: ignore[override]
151
+ """Add classes to the tag."""
150
152
current : list [str ] = self .tag .attributes .get ("class" , "" ).split ()
151
153
for cls in classes :
152
154
if cls not in current :
@@ -155,6 +157,7 @@ def add(self, *classes: str) -> tags.html_tag: # type: ignore[override]
155
157
return self .tag
156
158
157
159
def remove (self , * classes : str ) -> tags .html_tag : # type: ignore[override]
160
+ """Remove classes from the tag."""
158
161
current : list [str ] = self .tag .attributes .get ("class" , "" ).split ()
159
162
for cls in classes :
160
163
if cls in current :
@@ -163,9 +166,11 @@ def remove(self, *classes: str) -> tags.html_tag: # type: ignore[override]
163
166
return self .tag
164
167
165
168
def discard (self , value : str ) -> None :
169
+ """Remove a class if it exists."""
166
170
self .remove (value )
167
171
168
172
def swap (self , old : str , new : str ) -> tags .html_tag :
173
+ """Swap one class for another."""
169
174
current : list [str ] = self .tag .attributes .get ("class" , "" ).split ()
170
175
if old in current :
171
176
current .remove (old )
@@ -179,6 +184,7 @@ def swap(self, old: str, new: str) -> tags.html_tag:
179
184
class PrefixAccessor :
180
185
"""A helper for accessing attributes with a prefix."""
181
186
187
+ #: Attribute prefix
182
188
prefix : str = attrs .field ()
183
189
184
190
def __get__ (self , instance : tags .html_tag , owner : type [tags .html_tag ]) -> "PrefixAccess" :
@@ -188,7 +194,10 @@ def __get__(self, instance: tags.html_tag, owner: type[tags.html_tag]) -> "Prefi
188
194
@attrs .define
189
195
class PrefixAccess (MutableMapping [str , str ]):
190
196
197
+ #: Attribute prefix
191
198
prefix : str = attrs .field ()
199
+
200
+ #: The tag to access
192
201
tag : tags .html_tag = attrs .field ()
193
202
194
203
def __getitem__ (self , name : str ) -> str :
@@ -209,10 +218,12 @@ def __len__(self) -> int:
209
218
return sum (1 for _ in self )
210
219
211
220
def set (self , name : str , value : str ) -> tags .html_tag :
221
+ """Set an attribute with the given name."""
212
222
self [name ] = value
213
223
return self .tag
214
224
215
225
def remove (self , name : str ) -> tags .html_tag :
226
+ """Remove an attribute with the given name."""
216
227
del self [name ]
217
228
return self .tag
218
229
@@ -221,20 +232,30 @@ def remove(self, name: str) -> tags.html_tag:
221
232
class HtmlIDScope :
222
233
"""A helper for generating unique HTML IDs."""
223
234
235
+ #: A mapping of scopes to counters
224
236
scopes : collections .defaultdict [str , itertools .count ] = attrs .field (
225
237
factory = lambda : collections .defaultdict (itertools .count )
226
238
)
227
239
228
240
def __call__ (self , scope : str ) -> str :
241
+ """Generate a unique ID for a given scope.
242
+
243
+ Parameters
244
+ ----------
245
+ scope : str
246
+ Scopes are used to group IDs together, e.g. items in a list, or a form and its fields.
247
+ """
229
248
counter = next (self .scopes [scope ])
230
249
if counter == 0 :
231
250
return scope
232
251
return f"{ scope } -{ counter } "
233
252
234
253
def factory (self , scope : str ) -> functools .partial :
254
+ """Create a factory function for generating IDs in a specific scope."""
235
255
return functools .partial (self , scope )
236
256
237
257
def reset (self ) -> None :
258
+ """Reset all ID scopes."""
238
259
self .scopes .clear ()
239
260
240
261
@@ -279,7 +300,8 @@ class Tag(Generic[H]):
279
300
280
301
Holds the tag type as well as attributes for the tag. This can be used
281
302
by calling the instance as a function to create a tag, or by calling the
282
- :meth:`update` method to apply the attributes to an existing tag."""
303
+ :meth:`update` method to apply the attributes to an existing tag.
304
+ """
283
305
284
306
#: The tag type
285
307
tag : type [H ] = attrs .field ()
@@ -291,11 +313,18 @@ class Tag(Generic[H]):
291
313
attributes : dict [str , str ] = attrs .field (factory = dict )
292
314
293
315
def __tag__ (self ) -> H :
316
+ """Create a tag from the attributes and classes."""
294
317
tag = self .tag (** self .attributes )
295
318
tag .classes .add (* self .classes )
296
319
return tag
297
320
298
321
def __call__ (self , * args : Any , ** kwds : Any ) -> H :
322
+ """Create a tag from the attributes and classes.
323
+
324
+ This method is a convenience wrapper around :meth:`__tag__` that allows
325
+ the tag to be created with additional arguments and keyword arguments passed
326
+ to the tag constructor.
327
+ """
299
328
tag = self .tag (* args , ** {** self .attributes , ** kwds })
300
329
tag .classes .add (* self .classes )
301
330
return tag
@@ -307,6 +336,7 @@ def __getitem__(self, name: str) -> str:
307
336
return self .attributes [name ]
308
337
309
338
def update (self , tag : H ) -> H :
339
+ """Update the tag with the attributes and classes."""
310
340
tag .classes .add (* self .classes )
311
341
tag .attributes .update (self .attributes )
312
342
return tag
0 commit comments