11"""Wrappers over StateEngine based datamodel grpc service of Fluent."""
22
33from enum import Enum
4+ import itertools
45from typing import Any , Dict , Iterator , List , Tuple
56
67import grpc
@@ -363,7 +364,7 @@ def __init__(self, service: DatamodelService, rules: str, path: Path = None):
363364 else :
364365 self .path = path
365366
366- def __get_child_object_names (self ):
367+ def _get_child_object_names (self ):
367368 request = DataModelProtoModule .GetSpecsRequest ()
368369 request .rules = self .rules
369370 parent_path = self .path [0 :- 1 ]
@@ -379,9 +380,9 @@ def __get_child_object_names(self):
379380 child_object_names .append (member [len (child_type_suffix ) :])
380381 return child_object_names
381382
382- def __get_child_object_display_names (self ):
383+ def _get_child_object_display_names (self ):
383384 child_object_display_names = []
384- for name in self .__get_child_object_names ():
385+ for name in self ._get_child_object_names ():
385386 name_path = self .path [0 :- 1 ]
386387 name_path .append ((self .path [- 1 ][0 ], name ))
387388 name_path .append (("_name_" , "" ))
@@ -398,7 +399,7 @@ def __len__(self) -> int:
398399 int
399400 count
400401 """
401- return len (self .__get_child_object_display_names ())
402+ return len (self ._get_child_object_display_names ())
402403
403404 def __iter__ (self ) -> Iterator [PyMenu ]:
404405 """Returns the next child object.
@@ -408,15 +409,15 @@ def __iter__(self) -> Iterator[PyMenu]:
408409 Iterator[PyMenu]
409410 iterator of child objects
410411 """
411- for name in self .__get_child_object_display_names ():
412+ for name in self ._get_child_object_display_names ():
412413 child_path = self .path [:- 1 ]
413414 child_path .append ((self .path [- 1 ][0 ], name ))
414415 yield getattr (self .__class__ , f"_{ self .__class__ .__name__ } " )(
415416 self .service , self .rules , child_path
416417 )
417418
418- def __get_item (self , key : str ):
419- if key in self .__get_child_object_display_names ():
419+ def _get_item (self , key : str ):
420+ if key in self ._get_child_object_display_names ():
420421 child_path = self .path [:- 1 ]
421422 child_path .append ((self .path [- 1 ][0 ], key ))
422423 return getattr (self .__class__ , f"_{ self .__class__ .__name__ } " )(
@@ -427,8 +428,8 @@ def __get_item(self, key: str):
427428 f"{ key } is not found at path " f"{ _convert_path_to_se_path (self .path )} "
428429 )
429430
430- def __del_item (self , key : str ):
431- if key in self .__get_child_object_display_names ():
431+ def _del_item (self , key : str ):
432+ if key in self ._get_child_object_display_names ():
432433 child_path = self .path [:- 1 ]
433434 child_path .append ((self .path [- 1 ][0 ], key ))
434435 request = DataModelProtoModule .DeleteObjectRequest ()
@@ -453,7 +454,7 @@ def __getitem__(self, key: str) -> PyMenu:
453454 PyMenu
454455 child object
455456 """
456- return self .__get_item (key )
457+ return self ._get_item (key )
457458
458459 def __setitem__ (self , key : str , value : Any ):
459460 """Set state of the child object by name.
@@ -478,7 +479,7 @@ def __delitem__(self, key: str):
478479 key : str
479480 child name
480481 """
481- self .__del_item (key )
482+ self ._del_item (key )
482483
483484
484485class PyCommand :
@@ -537,3 +538,67 @@ def help(self) -> None:
537538 response .member , response .member .WhichOneof ("as" )
538539 ).common .helpstring
539540 print (help_string )
541+
542+
543+ class PyMenuGeneric (PyMenu ):
544+ attrs = ("service" , "rules" , "path" )
545+
546+ def _get_child_names (self ):
547+ request = DataModelProtoModule .GetSpecsRequest ()
548+ request .rules = self .rules
549+ request .path = _convert_path_to_se_path (self .path )
550+ response = self .service .get_specs (request )
551+ singleton_names = []
552+ creatable_type_names = []
553+ command_names = []
554+ for struct_type in ("singleton" , "namedobject" ):
555+ if response .member .HasField (struct_type ):
556+ struct_field = getattr (response .member , struct_type )
557+ for member in struct_field .members :
558+ if ":" not in member :
559+ singleton_names .append (member )
560+ creatable_type_names = struct_field .creatabletypes
561+ command_names = [x .name for x in struct_field .commands ]
562+ return singleton_names , creatable_type_names , command_names
563+
564+ def _get_child (self , name : str ):
565+ singletons , creatable_types , commands = self ._get_child_names ()
566+ if name in singletons :
567+ child_path = self .path + [(name , "" )]
568+ return PyMenuGeneric (self .service , self .rules , child_path )
569+ elif name in creatable_types :
570+ child_path = self .path + [(name , "" )]
571+ return PyNamedObjectContainerGeneric (self .service , self .rules , child_path )
572+ elif name in commands :
573+ return PyCommand (self .service , self .rules , name , self .path )
574+ else :
575+ raise LookupError (
576+ f"{ name } is not found at path " f"{ _convert_path_to_se_path (self .path )} "
577+ )
578+
579+ def __dir__ (self ):
580+ return list (itertools .chain (* self ._get_child_names ()))
581+
582+ def __getattr__ (self , name : str ):
583+ if name in PyMenuGeneric .attrs :
584+ return super ().__getattr__ (name )
585+ else :
586+ return self ._get_child (name )
587+
588+
589+ class PyNamedObjectContainerGeneric (PyNamedObjectContainer ):
590+ def __iter__ (self ):
591+ for name in self ._get_child_object_display_names ():
592+ child_path = self .path [:- 1 ]
593+ child_path .append ((self .path [- 1 ][0 ], name ))
594+ yield PyMenuGeneric (self .service , self .rules , child_path )
595+
596+ def _get_item (self , key : str ):
597+ if key in self ._get_child_object_display_names ():
598+ child_path = self .path [:- 1 ]
599+ child_path .append ((self .path [- 1 ][0 ], key ))
600+ return PyMenuGeneric (self .service , self .rules , child_path )
601+ else :
602+ raise LookupError (
603+ f"{ key } is not found at path " f"{ _convert_path_to_se_path (self .path )} "
604+ )
0 commit comments