Ignore:
Timestamp:
05/18/12 23:16:43 (12 years ago)
Author:
neise
Message:
more comments and unimportant stuff
File:
1 edited

Legend:

Unmodified
Added
Removed
  • fact/tools/PyDimCtrl/fpydim.py

    r13770 r13789  
    11#!/usr/bin/python -tti
     2
     3# for tab completion
    24import rlcompleter
    35import readline
    46readline.parse_and_bind('tab: complete')
    57
    6 import sys
    7 import pydim
    8 import types
    9 import time # for sleep
    10 from pprint import pprint
    11 from keyword import iskeyword
     8import sys      # for sys.exit() during bebugging mostly :-)
     9import types                    # for dynamic class construction
     10import time                     # for time.sleep
     11from pprint import pprint       # for nice printing
     12
     13from keyword import iskeyword   # in case dynamic methods are equal to keywords
     14
     15import pydim                    # for the C-API Dim Call Wrappers
     16
     17# using this line makes 'export DIM_DNS_NODE=daq' obsolete
    1218pydim.dic_set_dns_node('daq')
    1319
    14 # making server list
    15 rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C')
    16 # the output needs to be treated a bit .. it is a tuple with only one long string in it
    17 # the string contains | and the strange character \x00
    18 # I use both to cut the list apart
    19 rawlist = rawlist[0].split('\x00')
    20 servers_n_hosts = rawlist[0].split('|')
    21 server_ids = rawlist[1].split('|')
    22 
    23 servers = {}
    24 for i,snh in enumerate(servers_n_hosts):
    25         snh = snh.split('@')
    26         s = snh[0]
    27         h = snh[1]
    28         sid = server_ids[i]
    29         servers[s] = (sid, h)
    30 
    31 # delete unneeded vars
    32 del servers_n_hosts
    33 del rawlist
    34 del server_ids
    35 
    36 # print servers
    37 
    38 # make service list
    39 services = {}
    40 dd = {}
    41 for serv in servers.keys():
    42         # print serv+'/SERVICE_LIST'
    43         sl_raw = pydim.dic_sync_info_service(serv+'/SERVICE_LIST','C')[0]
    44         if serv+'/SERVICE_DESC' in sl_raw:
    45                 sd_raw = pydim.dic_sync_info_service(serv+'/SERVICE_DESC','C')[0]
    46         else:
    47                 # print "Warning:", serv+'/SERVICE_DESC' , "not in SERVICE_LIST of", serv
    48                 sd_raw = ''
    49         sl_raw = sl_raw.rstrip('\x00\n')
    50         sl_raw = sl_raw.replace('\x00','')
    51         sd_raw = sd_raw.rstrip('\x00\n')
    52         sl = sl_raw.split('\n')
    53         sd = sd_raw.split('\n')
    54        
    55         # create descripton dict dd from service_desc list sd
    56         for d_str in sd:
    57                 service,equalsign,desc = d_str.partition('=')
    58                 #if '=' != equalsign:
    59                         # print "Error: server:", serv, "desc:", d_str
    60                 dd[service] = desc
    61 
    62 
    63         services[serv] = {}
    64         for service in sl:
    65                 service = service.split('|')
    66                 if service[0] in dd:
    67                         services[serv][service[0]] = (
    68                                         service[1], service[2], dd[service[0]])
    69          #      else:
    70                         # print service[0], 'has no DESC in SERVICE_DESC'
    71 
    72 # pprint( services )
    73 
    7420class FactDimServer( object ):
    7521
    76         def __init__(self, name):
    77                 self.name = name
    78 
    79         def cmd(self, cmdstr, *args):
    80                 #args = cmdstr.split(' ')
    81                 #for i in range(len(args)):
    82         #               i = len(args)-1-i
    83         #               if not args[i]:
    84         #                       del args[i]
    85                 cmdstr=self.name+'/'+cmdstr.upper()
    86         #       args = tuple(args[1:])
    87                 desc = services[self.name][cmdstr.upper()][0]
    88                 # there is a bug in the pydim library ...
    89                 # even if a command need no argument
    90                 # one has to give one ... need to tell Niko about it.
    91                 if len(desc) == 0:
    92                         desc = 'I'
    93                         args=(1,)
    94                 # print 'cmd: cmdstr:', cmdstr,
    95                 # print '-args:', args,
    96                 # print '-desc:', desc
    97                 pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None)
    98         def get(self, service):
    99                 full_srv_name = self.name+'/'+service.upper()
    100                 desc = services[self.name][full_srv_name][0]
    101                 return pydim.dic_sync_info_service(full_srv_name, desc)
    102 
    103         def __call__(self):
    104                 """ get Server State as numeric code
    105                     for convenience
    106                 """
    107                 if hasattr(self, 'state'):
    108                         s = self.state()[0]
    109                         return int(s[ s.find('[')+1 : s.find(']') ])
    110                 else:
    111                         raise TypeError(self.name+' has no CMD called STATE')
    112        
    113         def wait(self, state_num, timeout=None):
    114                 """ waits for a certain state
    115                         BLOCKING
    116                         returns True if state was reached
    117                         returns False if timeout occured
    118                         raises TypeError if Server has no method state
    119                 """
    120 
    121                 if not hasattr(self, 'state'):
    122                         raise TypeError(self.name+' has no CMD called STATE')
    123                 if timeout == None:
    124                         timeout = float('inf')
    125                 else:
    126                         timeout = float(timeout)
    127                 start = time.time()
    128                 while not self() == state_num:
    129                         time.sleep(0.1)
    130                         if time.time() >= start+timeout:
    131                                 return False
    132                 return True
     22    def __init__(self, name):
     23        """ sets name of instance to name of server, all uppercase
     24        """
     25        self.name = name.upper()
     26
     27    def _cmd(self, cmdstr, *args):
     28        """ used by all dynamicly created methods, which call a Dim CMD
     29        """
     30        cmdstr=self.name+'/'+cmdstr.upper()
     31        desc = services[self.name][cmdstr.upper()][0]
     32       
     33        # there is a work around for a bug in pydim
     34        # even if a command needs no argument, and desc is also empty string
     35        # one has to give one ... need to tell Niko about it.
     36        if not desc:
     37            desc = 'I'
     38            args=(1,)
     39        pydim.dic_sync_cmnd_service(cmdstr, args, desc, timeout=None)
     40
     41
     42    def _get(self, service):
     43        """ used by all dynamicly created methods, which get a service
     44        """
     45        full_srv_name = self.name+'/'+service.upper()
     46        desc = services[self.name][full_srv_name][0]
     47        return pydim.dic_sync_info_service(full_srv_name, desc)
     48
     49
     50    def __call__(self):
     51        """ Wrapper / For Convenience
     52            self.state() returns a string (if it exists)
     53            *returns* numeric state code, parsed from return of self.state()
     54        """
     55        if hasattr(self, 'state'):
     56            s = self.state()[0]
     57            return int(s[ s.find('[')+1 : s.find(']') ])
     58        else:
     59            raise TypeError(self.name+' has no CMD called STATE')
     60   
     61    def wait(self, state_num, timeout=None):
     62        """ waits for a certain state
     63            BLOCKING
     64            returns True if state was reached
     65            returns False if timeout occured
     66            raises TypeError if Server has no method state
     67        """
     68
     69        if not hasattr(self, 'state'):
     70            raise TypeError(self.name+' has no CMD called STATE')
     71        if timeout == None:
     72            timeout = float('inf')
     73        else:
     74            timeout = float(timeout)
     75        start = time.time()
     76        while not self() == state_num:
     77            time.sleep(0.1)
     78            if time.time() >= start+timeout:
     79                return False
     80        return True
     81
     82
     83
     84# utility functions for dynamic addid of methods to classes
     85def add_command(cls, name):
     86    meth_name = name.split('/')[1].lower()
     87    if iskeyword(meth_name):
     88        meth_name += '_cmd'
     89       
     90    # this is the new command, it simple calls the _cmd() method
     91    def new_command(self, *args):
     92        self._cmd(meth_name, *args)
     93       
     94    new_command.__name__ = meth_name
     95   
     96    # from this line on, the docstring of the method is created
     97    if name in dd:
     98        if not dd[name]:
     99            new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
     100        else:
     101            new_command.__doc__ = dd[name]
     102    else:
     103        new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
     104    new_command.__doc__ += '\n'
     105    new_command.__doc__ += services[name.split('/')[0]][name][0]
     106   
     107    # this line make the new_command() method, a method of the class cls
     108    # giving it the name new_command.__name__
     109    setattr( cls, new_command.__name__, new_command)
     110
     111# add_getter is very similar to add_command,
     112# the only difference is, that it calls _get() instead of _cmd()
     113# and since _get() has a return value, this return value is vorwarded to the user
     114def add_getter(cls, name):
     115    meth_name = name.split('/')[1].lower()
     116    if iskeyword(meth_name):
     117        meth_name += '_cmd'
     118    def new_command(self):
     119        return self._get(meth_name)
     120    new_command.__name__ = meth_name
     121    if name in dd:
     122        if not dd[name]:
     123            new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
     124        else:
     125            new_command.__doc__ = dd[name]
     126    else:
     127        new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
     128    new_command.__doc__ += '\n'
     129    new_command.__doc__ += services[name.split('/')[0]][name][0]
     130    setattr( cls, new_command.__name__, new_command)
     131
     132
     133
     134
     135
     136# In order to create classes according to the Dim-Servers, currently connected
     137# to the DIS_DNS I have to parse DIS_DNS/SERVER_LIST
     138# This is done in two steps, first I get the list of Server Names from DIS_DNS
     139# and the I get the list of each servers services and cmds,
     140# from each servers SERVICE_LIST and the service/command description
     141# from each servers SERVICE_DESC
     142# I get quite a lot of information, which I store in python dicts, or
     143# even nested dicts, if necessary.
     144
     145def ParseDnsServerList():
     146    # making server list
     147    rawlist = pydim.dic_sync_info_service('DIS_DNS/SERVER_LIST','C')
     148    # the output needs to be treated a bit .. it is a tuple with only one long string in it
     149    # the string contains | and the strange character \x00
     150    # I use both to cut the list apart
     151    rawlist = rawlist[0].split('\x00')
     152    servers_n_hosts = rawlist[0].split('|')
     153    server_ids = rawlist[1].split('|')
     154
     155    servers = {}
     156    for i,snh in enumerate(servers_n_hosts):
     157        snh = snh.split('@')
     158        s = snh[0]
     159        h = snh[1]
     160        sid = server_ids[i]
     161        servers[s] = (sid, h)
     162
     163    return servers
     164
     165
     166
     167# servers should be a dict containing uppercase server names as keys,
     168# the values are not needed, so it might be any iteratable python listlike type
     169# to be precise
     170def ParseServersServiceList( servers )
     171   
     172    services = {}
     173    dd = {}
     174    for server in servers:
     175        # sl_raw is a tuple, with an really long string, which needs to be parsed
     176        sl_raw = pydim.dic_sync_info_service(server+'/SERVICE_LIST','C')[0]
     177       
     178        # even without parsing, I can find out, if this server also gives me a
     179        # service description list. In case it does not, this is fine as well
     180        # the doc string of the dynamicly created methods, will then contain
     181        # a note, that therer was no SERVICE_DESC ...
     182        if server+'/SERVICE_DESC' in sl_raw:
     183            sd_raw = pydim.dic_sync_info_service(server+'/SERVICE_DESC','C')[0]
     184        else:
     185            sd_raw = ''
     186       
     187        # now before parsing, I strip off all ASCII zeroes '\x00' and all
     188        # line breaks off the *end* of the long string of both
     189        # the service list sl
     190        # and service description sd
     191        #
     192        # I think in sl_raw were alse some '\x00' in the middle .. these
     193        # are replaced by nothing, in case they are there.
     194        sl_raw = sl_raw.rstrip('\x00\n')
     195        sl_raw = sl_raw.replace('\x00','')
     196        sd_raw = sd_raw.rstrip('\x00\n')
     197       
     198        # The lists are seperated by line breaks, so I split them using this
     199        sl = sl_raw.split('\n')
     200        sd = sd_raw.split('\n')
     201       
     202        # First I parse the service descriptons, so I have them available,
     203        # when I create the dict full of services.
     204        # All desciptions look like this
     205        # 'SERVER/SERVICE=some descriptive text' or
     206        # 'SERVER/SERVICE='
     207        # this I use to create the dictionary.
     208        # create descripton dict dd from service_desc list sd
     209        for d_str in sd:
     210            service,equalsign,desc = d_str.partition('=')
     211            #if '=' != equalsign:
     212                # print "Error: server:", server, "desc:", d_str
     213            dd[service] = desc
     214
     215        # Now I fill ther services dict. Each server gets a nested dict
     216        # inside services.
     217        # Each service is explained in a string with a '|' in between.
     218        # I use this for spliting.
     219        # The string look like this
     220        # SERVER/SERVICE|format-desc-str(e.g. I:2;C)|-empty- or CMD or RPC|
     221        services[server] = {}
     222        for service in sl:
     223            service = service.split('|')
     224            if service[0] in dd:
     225                services[server][service[0]] = (
     226                        service[1], service[2], dd[service[0]])
     227    return services
     228
     229
     230servers = ParseDnsServerList()
     231services = ParseServersServiceList( servers )
     232
    133233# create one class for each Fact Dim Server
    134234FactDimServerClasses = []
    135235for server_name in servers:
    136         FactDimServerClasses.append(
    137                         types.ClassType( server_name, (FactDimServer,), {}) )
     236    FactDimServerClasses.append(
     237            types.ClassType( server_name, (FactDimServer,), {}) )
    138238
    139239# create an instace of each of the classes
     
    143243all_dims = []
    144244for i,server_name in enumerate(servers):
    145         new_instance = FactDimServerClasses[i](server_name)
    146         all_dims.append( new_instance )
     245    new_instance = FactDimServerClasses[i](server_name)
     246    all_dims.append( new_instance )
    147247del new_instance
    148248
     
    150250#print "connecting to Dim Servers... "
    151251for dim in all_dims:
    152 #       print dim.name.lower()
    153         if dim.name == 'DIS_DNS':
    154                 continue
    155         globals()[dim.name.lower()] = dim
    156         dims.append(dim)
    157 
    158 # utility class for dynamic addid of methods to classes
    159 def add_command(cls, name):
    160         meth_name = name.split('/')[1].lower()
    161         if iskeyword(meth_name):
    162                 meth_name += '_cmd'
    163         def new_command(self, *args):
    164                 self.cmd(meth_name, *args)
    165         new_command.__name__ = meth_name
    166         if name in dd:
    167                 if not dd[name]:
    168                         new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
    169                 else:
    170                         new_command.__doc__ = dd[name]
    171         else:
    172                 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
    173         new_command.__doc__ += '\n'
    174         new_command.__doc__ += services[name.split('/')[0]][name][0]
    175         setattr( cls, new_command.__name__, new_command)
    176 
    177 def add_getter(cls, name):
    178         meth_name = name.split('/')[1].lower()
    179         if iskeyword(meth_name):
    180                 meth_name += '_cmd'
    181         def new_command(self):
    182                 return self.get(meth_name)
    183         new_command.__name__ = meth_name
    184         if name in dd:
    185                 if not dd[name]:
    186                         new_command.__doc__ = "DESC in SERVICE_DESC is empty ?!"
    187                 else:
    188                         new_command.__doc__ = dd[name]
    189         else:
    190                 new_command.__doc__ = "-- no DESC found in SERVICE_DESC --"
    191         new_command.__doc__ += '\n'
    192         new_command.__doc__ += services[name.split('/')[0]][name][0]
    193         setattr( cls, new_command.__name__, new_command)
     252#    print dim.name.lower()
     253    if dim.name == 'DIS_DNS':
     254        continue
     255    globals()[dim.name.lower()] = dim
     256    dims.append(dim)
    194257
    195258for i,dim in enumerate(all_dims):
    196         for cmd in services[dim.name]:
    197                 if 'CMD' in services[dim.name][cmd][1]:
    198                         cmdname = cmd.split('/')[1]
    199                         add_command(FactDimServerClasses[i], cmd)
    200                 elif not services[dim.name][cmd][1]:
    201                         cmdname = cmd.split('/')[1]
    202                         add_getter(FactDimServerClasses[i], cmd)
    203 
     259    for cmd in services[dim.name]:
     260        if 'CMD' in services[dim.name][cmd][1]:
     261            cmdname = cmd.split('/')[1]
     262            add_command(FactDimServerClasses[i], cmd)
     263        elif not services[dim.name][cmd][1]:
     264            cmdname = cmd.split('/')[1]
     265            add_getter(FactDimServerClasses[i], cmd)
     266
     267##############################################################################
     268# class for colored printing
    204269
    205270class bcolors:
    206             HEADER = '\033[95m'
    207             OKBLUE = '\033[94m'
    208             OKGREEN = '\033[92m'
    209             WARNING = '\033[93m'
    210             FAIL = '\033[91m'
    211             ENDC = '\033[0m'
    212 
    213             def disable(self):
    214                 self.HEADER = ''
    215                 self.OKBLUE = ''
    216                 self.OKGREEN = ''
    217                 self.WARNING = ''
    218                 self.FAIL = ''
    219                 self.ENDC = ''
     271        HEADER = '\033[95m'
     272        OKBLUE = '\033[94m'
     273        OKGREEN = '\033[92m'
     274        WARNING = '\033[93m'
     275        FAIL = '\033[91m'
     276        ENDC = '\033[0m'
     277
     278        def disable(self):
     279            self.HEADER = ''
     280            self.OKBLUE = ''
     281            self.OKGREEN = ''
     282            self.WARNING = ''
     283            self.FAIL = ''
     284            self.ENDC = ''
     285
     286##############################################################################
     287# class which implements colored printing
     288# method calls can be used instead of Python print calls
     289# for conveniently printing colored output.
     290
     291
    220292class MSG( bcolors):
    221         def __init__(self, verbose = True):
    222                 self.output = verbose
    223        
    224         def fail(self, text ):
    225                 text = str(text)
    226                 if self.output:
    227                         print bcolors.FAIL + "ERROR:" + bcolors.ENDC,
    228                         print bcolors.FAIL + text + bcolors.ENDC
    229 
    230         def warn(self, text ):
    231                 text = str(text)
    232                 if self.output:
    233                         print bcolors.WARNING + text + bcolors.ENDC
    234 
    235         def ok(self, text ):
    236                 text = str(text)
    237                 if self.output:
    238                         print bcolors.OKGREEN + text + bcolors.ENDC
    239 
    240         def __call__(self, *args):
    241                 if self.output:
    242                         for arg in args:
    243                                 print arg,
    244                         print
    245 
     293    def __init__(self, verbose = True):
     294        """ create MSG instance,
     295            default is verbose,
     296            sets self.output
     297           
     298            if:
     299            self.*output* = True, object behaves as expeted
     300            if False, no call return anything
     301        """
     302        self.output = verbose
     303   
     304    def fail(self, text ):
     305        """ print in RED
     306        """
     307        text = str(text)
     308        if self.output:
     309            print bcolors.FAIL + "ERROR:" + bcolors.ENDC,
     310            print bcolors.FAIL + text + bcolors.ENDC
     311
     312    def warn(self, text ):
     313        """ print in YELLOW
     314        """
     315        text = str(text)
     316        if self.output:
     317            print bcolors.WARNING + text + bcolors.ENDC
     318
     319    def ok(self, text ):
     320        """ print in GREEN
     321        """
     322        text = str(text)
     323        if self.output:
     324            print bcolors.OKGREEN + text + bcolors.ENDC
     325
     326    def __call__(self, *args):
     327        """ print as Python print would do
     328        """
     329        if self.output:
     330            for arg in args:
     331                print arg,
     332            print
     333
Note: See TracChangeset for help on using the changeset viewer.