1515limitations under the License.
1616"""
1717from inspect import isclass
18- from typing import Callable , ClassVar , Dict , List , Mapping , Optional , Text , Tuple , Type , Union
18+ from typing import Callable , ClassVar , Dict , List , Mapping , Optional , Text , Tuple , Type , Union , Any , Set
1919
2020from pydantic import BaseModel , PrivateAttr
2121import structlog # type: ignore
@@ -72,7 +72,7 @@ class DiffSyncModel(BaseModel):
7272 Note: inclusion in `_attributes` is mutually exclusive from inclusion in `_identifiers`; a field cannot be in both!
7373 """
7474
75- _children : ClassVar [Mapping [str , str ]] = {}
75+ _children : ClassVar [Dict [str , str ]] = {}
7676 """Optional: dict of `{_modelname: field_name}` entries describing how to store "child" models in this model.
7777
7878 When calculating a Diff or performing a sync, DiffSync will automatically recurse into these child models.
@@ -101,7 +101,7 @@ class Config: # pylint: disable=too-few-public-methods
101101 # Let us have a DiffSync as an instance variable even though DiffSync is not a Pydantic model itself.
102102 arbitrary_types_allowed = True
103103
104- def __init_subclass__ (cls ):
104+ def __init_subclass__ (cls ) -> None :
105105 """Validate that the various class attribute declarations correspond to actual instance fields.
106106
107107 Called automatically on subclass declaration.
@@ -132,27 +132,27 @@ def __init_subclass__(cls):
132132 if attr_child_overlap :
133133 raise AttributeError (f"Fields { attr_child_overlap } are included in both _attributes and _children." )
134134
135- def __repr__ (self ):
135+ def __repr__ (self ) -> str :
136136 return f'{ self .get_type ()} "{ self .get_unique_id ()} "'
137137
138- def __str__ (self ):
138+ def __str__ (self ) -> str :
139139 return self .get_unique_id ()
140140
141- def dict (self , ** kwargs ) -> dict :
141+ def dict (self , ** kwargs : Any ) -> Dict :
142142 """Convert this DiffSyncModel to a dict, excluding the diffsync field by default as it is not serializable."""
143143 if "exclude" not in kwargs :
144144 kwargs ["exclude" ] = {"diffsync" }
145145 return super ().dict (** kwargs )
146146
147- def json (self , ** kwargs ) -> str :
147+ def json (self , ** kwargs : Any ) -> str :
148148 """Convert this DiffSyncModel to a JSON string, excluding the diffsync field by default as it is not serializable."""
149149 if "exclude" not in kwargs :
150150 kwargs ["exclude" ] = {"diffsync" }
151151 if "exclude_defaults" not in kwargs :
152152 kwargs ["exclude_defaults" ] = True
153153 return super ().json (** kwargs )
154154
155- def str (self , include_children : bool = True , indent : int = 0 ) -> str :
155+ def to_detailed_string (self , include_children : bool = True , indent : int = 0 ) -> str :
156156 """Build a detailed string representation of this DiffSyncModel and optionally its children."""
157157 margin = " " * indent
158158 output = f"{ margin } { self .get_type ()} : { self .get_unique_id ()} : { self .get_attrs ()} "
@@ -167,12 +167,12 @@ def str(self, include_children: bool = True, indent: int = 0) -> str:
167167 for child_id in child_ids :
168168 try :
169169 child = self .diffsync .get (modelname , child_id )
170- output += "\n " + child .str (include_children = include_children , indent = indent + 4 )
170+ output += "\n " + child .to_detailed_string (include_children = include_children , indent = indent + 4 )
171171 except ObjectNotFound :
172172 output += f"\n { margin } { child_id } (ERROR: details unavailable)"
173173 return output
174174
175- def set_status (self , status : DiffSyncStatus , message : Text = "" ):
175+ def set_status (self , status : DiffSyncStatus , message : Text = "" ) -> None :
176176 """Update the status (and optionally status message) of this model in response to a create/update/delete call."""
177177 self ._status = status
178178 self ._status_message = message
@@ -288,7 +288,7 @@ def get_type(cls) -> Text:
288288 return cls ._modelname
289289
290290 @classmethod
291- def create_unique_id (cls , ** identifiers ) -> Text :
291+ def create_unique_id (cls , ** identifiers : Dict [ str , Any ] ) -> str :
292292 """Construct a unique identifier for this model class.
293293
294294 Args:
@@ -297,7 +297,7 @@ def create_unique_id(cls, **identifiers) -> Text:
297297 return "__" .join (str (identifiers [key ]) for key in cls ._identifiers )
298298
299299 @classmethod
300- def get_children_mapping (cls ) -> Mapping [ Text , Text ]:
300+ def get_children_mapping (cls ) -> Dict [ str , str ]:
301301 """Get the mapping of types to fieldnames for child models of this model."""
302302 return cls ._children
303303
@@ -347,9 +347,9 @@ def get_shortname(self) -> Text:
347347
348348 def get_status (self ) -> Tuple [DiffSyncStatus , Text ]:
349349 """Get the status of the last create/update/delete operation on this object, and any associated message."""
350- return ( self ._status , self ._status_message )
350+ return self ._status , self ._status_message
351351
352- def add_child (self , child : "DiffSyncModel" ):
352+ def add_child (self , child : "DiffSyncModel" ) -> None :
353353 """Add a child reference to an object.
354354
355355 The child object isn't stored, only its unique id.
@@ -373,7 +373,7 @@ def add_child(self, child: "DiffSyncModel"):
373373 raise ObjectAlreadyExists (f"Already storing a { child_type } with unique_id { child .get_unique_id ()} " , child )
374374 childs .append (child .get_unique_id ())
375375
376- def remove_child (self , child : "DiffSyncModel" ):
376+ def remove_child (self , child : "DiffSyncModel" ) -> None :
377377 """Remove a child reference from an object.
378378
379379 The name of the storage attribute is defined in `_children` per object type.
@@ -404,13 +404,15 @@ class DiffSync: # pylint: disable=too-many-public-methods
404404 # modelname1 = MyModelClass1
405405 # modelname2 = MyModelClass2
406406
407- type : ClassVar [ Optional [str ] ] = None
407+ type : Optional [str ] = None
408408 """Type of the object, will default to the name of the class if not provided."""
409409
410410 top_level : ClassVar [List [str ]] = []
411411 """List of top-level modelnames to begin from when diffing or synchronizing."""
412412
413- def __init__ (self , name = None , internal_storage_engine = LocalStore ):
413+ def __init__ (
414+ self , name : Optional [str ] = None , internal_storage_engine : Union [Type [BaseStore ], BaseStore ] = LocalStore
415+ ) -> None :
414416 """Generic initialization function.
415417
416418 Subclasses should be careful to call super().__init__() if they override this method.
@@ -429,7 +431,7 @@ def __init__(self, name=None, internal_storage_engine=LocalStore):
429431 # If the name has not been provided, use the type as the name
430432 self .name = name if name else self .type
431433
432- def __init_subclass__ (cls ):
434+ def __init_subclass__ (cls ) -> None :
433435 """Validate that references to specific DiffSyncModels use the correct modelnames.
434436
435437 Called automatically on subclass declaration.
@@ -448,16 +450,16 @@ def __init_subclass__(cls):
448450 if not isclass (value ) or not issubclass (value , DiffSyncModel ):
449451 raise AttributeError (f'top_level references attribute "{ name } " but it is not a DiffSyncModel subclass!' )
450452
451- def __str__ (self ):
453+ def __str__ (self ) -> str :
452454 """String representation of a DiffSync."""
453455 if self .type != self .name :
454456 return f'{ self .type } "{ self .name } "'
455457 return self .type
456458
457- def __repr__ (self ):
459+ def __repr__ (self ) -> str :
458460 return f"<{ str (self )} >"
459461
460- def __len__ (self ):
462+ def __len__ (self ) -> int :
461463 """Total number of elements stored."""
462464 return self .store .count ()
463465
@@ -481,11 +483,11 @@ def _get_initial_value_order(cls) -> List[str]:
481483 value_order .append (item )
482484 return value_order
483485
484- def load (self ):
486+ def load (self ) -> None :
485487 """Load all desired data from whatever backend data source into this instance."""
486488 # No-op in this generic class
487489
488- def dict (self , exclude_defaults : bool = True , ** kwargs ) -> Mapping :
490+ def dict (self , exclude_defaults : bool = True , ** kwargs : Any ) -> Dict [ str , Dict [ str , Dict ]] :
489491 """Represent the DiffSync contents as a dict, as if it were a Pydantic model."""
490492 data : Dict [str , Dict [str , Dict ]] = {}
491493 for modelname in self .store .get_all_model_names ():
@@ -494,7 +496,7 @@ def dict(self, exclude_defaults: bool = True, **kwargs) -> Mapping:
494496 data [obj .get_type ()][obj .get_unique_id ()] = obj .dict (exclude_defaults = exclude_defaults , ** kwargs )
495497 return data
496498
497- def str (self , indent : int = 0 ) -> str :
499+ def to_detailed_string (self , indent : int = 0 ) -> str :
498500 """Build a detailed string representation of this DiffSync."""
499501 margin = " " * indent
500502 output = ""
@@ -507,10 +509,10 @@ def str(self, indent: int = 0) -> str:
507509 output += ": []"
508510 else :
509511 for model in models :
510- output += "\n " + model .str (indent = indent + 2 )
512+ output += "\n " + model .to_detailed_string (indent = indent + 2 )
511513 return output
512514
513- def load_from_dict (self , data : Dict ):
515+ def load_from_dict (self , data : Dict ) -> None :
514516 """The reverse of `dict` method, taking a dictionary and loading into the inventory.
515517
516518 Args:
@@ -594,7 +596,7 @@ def sync_complete(
594596 diff : Diff ,
595597 flags : DiffSyncFlags = DiffSyncFlags .NONE ,
596598 logger : Optional [structlog .BoundLogger ] = None ,
597- ):
599+ ) -> None :
598600 """Callback triggered after a `sync_from` operation has completed and updated the model data of this instance.
599601
600602 Note that this callback is **only** triggered if the sync actually resulted in data changes. If there are no
@@ -657,11 +659,11 @@ def diff_to(
657659 # Object Storage Management
658660 # ------------------------------------------------------------------------------
659661
660- def get_all_model_names (self ):
662+ def get_all_model_names (self ) -> Set [ str ] :
661663 """Get all model names.
662664
663665 Returns:
664- List[str]: List of model names
666+ List of model names
665667 """
666668 return self .store .get_all_model_names ()
667669
@@ -730,7 +732,7 @@ def get_tree_traversal(cls, as_dict: bool = False) -> Union[Text, Mapping]:
730732 """Get a string describing the tree traversal for the diffsync object.
731733
732734 Args:
733- as_dict: Whether or not to return as a dictionary
735+ as_dict: Whether to return as a dictionary
734736
735737 Returns:
736738 A string or dictionary representation of tree
@@ -751,7 +753,7 @@ def get_tree_traversal(cls, as_dict: bool = False) -> Union[Text, Mapping]:
751753 return output_dict
752754 return tree_string (output_dict , cls .__name__ )
753755
754- def add (self , obj : DiffSyncModel ):
756+ def add (self , obj : DiffSyncModel ) -> None :
755757 """Add a DiffSyncModel object to the store.
756758
757759 Args:
@@ -762,7 +764,7 @@ def add(self, obj: DiffSyncModel):
762764 """
763765 return self .store .add (obj = obj )
764766
765- def update (self , obj : DiffSyncModel ):
767+ def update (self , obj : DiffSyncModel ) -> None :
766768 """Update a DiffSyncModel object to the store.
767769
768770 Args:
@@ -773,7 +775,7 @@ def update(self, obj: DiffSyncModel):
773775 """
774776 return self .store .update (obj = obj )
775777
776- def remove (self , obj : DiffSyncModel , remove_children : bool = False ):
778+ def remove (self , obj : DiffSyncModel , remove_children : bool = False ) -> None :
777779 """Remove a DiffSyncModel object from the store.
778780
779781 Args:
@@ -835,14 +837,14 @@ def update_or_add_model_instance(self, obj: DiffSyncModel) -> Tuple[DiffSyncMode
835837 """
836838 return self .store .update_or_add_model_instance (obj = obj )
837839
838- def count (self , model : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ], None ] = None ):
840+ def count (self , model : Union [Text , "DiffSyncModel" , Type ["DiffSyncModel" ], None ] = None ) -> int :
839841 """Count how many objects of one model type exist in the backend store.
840842
841843 Args:
842844 model (DiffSyncModel): The DiffSyncModel to check the number of elements. If not provided, default to all.
843845
844846 Returns:
845- Int: Number of elements of the model type
847+ Number of elements of the model type
846848 """
847849 return self .store .count (model = model )
848850
0 commit comments