@@ -224,6 +224,150 @@ def owner(self, value: str) -> None:
224224 generic._set_ephemeral_attr(self , " owner" , value)
225225```
226226
227+ ### Mixin Properties
228+
229+ Mixin properties follow the same API standards as regular properties. They provide consistent getter/setter behavior with change tracking.
230+
231+ #### Mixin Property Docstrings
232+
233+ Mixin properties MUST include docstrings that describe the property:
234+
235+ ``` python
236+ class NamedObjectMixin :
237+ """ Mixin providing name property with change tracking."""
238+
239+ @ property
240+ def name (self ) -> str :
241+ """ The object's name.
242+
243+ Returns:
244+ The name of the database object.
245+ """
246+ return self ._name
247+
248+ @name.setter
249+ def name (self , value : str ) -> None :
250+ """ Set the object's name.
251+
252+ Changes are queued and applied when alter() is called.
253+
254+ Args:
255+ value: New name for the object.
256+
257+ Example:
258+ >>> table.name = "new_table_name"
259+ >>> table.alter() # Apply the name change
260+ """
261+ from . import generic
262+ generic._set_ephemeral_attr(self , " name" , value)
263+ ```
264+
265+ #### Mixin Initialization in Object __ init__
266+
267+ Objects using mixins MUST call mixin initialization methods in their ` __init__ ` :
268+
269+ ``` python
270+ class Table (
271+ NamedObjectMixin ,
272+ OwnedObjectMixin ,
273+ SchemaObjectMixin ,
274+ _DynamicObject ,
275+ _CollectionChild
276+ ):
277+ """ Postgres Table object.
278+
279+ Args:
280+ name: Table name
281+ schema: Schema name (default: 'public')
282+ owner: Table owner
283+ cluster: Postgres cluster object
284+ parent: Parent collection
285+ oid: Table OID
286+
287+ Attributes:
288+ name: Table name (from NamedObjectMixin)
289+ owner: Table owner (from OwnedObjectMixin)
290+ schema: Schema name (from SchemaObjectMixin)
291+ tablespace: Tablespace (from TablespaceObjectMixin)
292+ row_security: Whether row security is enabled
293+ oid: Table OID
294+ """
295+
296+ def __init__ (
297+ self ,
298+ name : str ,
299+ schema : str = " public" ,
300+ owner : Optional[str ] = None ,
301+ cluster : " Cluster" = None ,
302+ parent : " TableCollection" = None ,
303+ oid : Optional[int ] = None
304+ ):
305+ # Initialize base classes
306+ super ().__init__ (kind = " TABLE" , cluster = cluster, oid = oid, name = name, schema = schema)
307+ _CollectionChild.__init__ (self , parent = parent)
308+
309+ # Initialize mixins - REQUIRED for mixin properties to work
310+ self ._init_name(name)
311+ self ._init_owner(owner)
312+ self ._init_schema(schema)
313+ self ._init_tablespace(None )
314+
315+ # Table-specific attributes
316+ self ._row_security: bool = False
317+ ```
318+
319+ #### Documenting Mixin Properties in Class Docstrings
320+
321+ When a class uses mixins, document which properties come from mixins in the class docstring:
322+
323+ ``` python
324+ class Sequence (
325+ NamedObjectMixin ,
326+ OwnedObjectMixin ,
327+ SchemaObjectMixin ,
328+ _DynamicObject ,
329+ _CollectionChild
330+ ):
331+ """ Postgres sequence object.
332+
333+ Attributes:
334+ name: Sequence name (from NamedObjectMixin)
335+ owner: Sequence owner (from OwnedObjectMixin)
336+ schema: Schema name (from SchemaObjectMixin)
337+ data_type: Data type of the sequence
338+ start_value: Starting value
339+ increment_by: Increment value
340+ min_value: Minimum value
341+ max_value: Maximum value
342+ """
343+ ```
344+
345+ #### Mixin Property Behavior
346+
347+ Mixin properties behave identically to regular properties:
348+
349+ - ** Getters** : Return the current value
350+ - ** Setters** : Queue changes via ` _set_ephemeral_attr() ` for later application
351+ - ** Change tracking** : Changes are stored in ` self._changes ` dictionary
352+ - ** Application** : Changes are applied when ` alter() ` is called
353+
354+ ``` python
355+ # Using mixin properties
356+ table = cluster.tables[" users" ]
357+
358+ # Get property (from NamedObjectMixin)
359+ print (table.name) # "users"
360+
361+ # Set property (queues change)
362+ table.name = " app_users"
363+
364+ # Property is updated locally
365+ print (table.name) # "app_users"
366+
367+ # Apply change to database
368+ table.alter() # Executes: ALTER TABLE users RENAME TO app_users
369+ ```
370+
227371### Lazy Properties
228372``` python
229373from ._decorators import get_lazy_property
0 commit comments