Best Python code snippet using pyatom_python
vissim_v5.py
Source:vissim_v5.py  
1#!/usr/bin/env python2""" VISSIM Tools v2.0 """3from re import findall as _findall, match as _match, search as _search4from re import split as _split5from math import sqrt as _sqrt6from copy import copy as _copy789def _median(lst):10    """ Stock median function from: http://stackoverflow.11    com/questions/24101524/finding-median-of-list-in-python12    """13    lst = sorted(lst)14    if len(lst) < 1:15        return None16    if len(lst) % 2 == 1:17        return lst[((len(lst) + 1) / 2) - 1]18    else:19        return float(sum(lst[(len(lst) / 2) - 1:(len(lst) / 2) + 1])) / 2.0202122def _flatten(coll):23    """ Flatten list and convert elements to int24    """25    if isinstance(coll, list):26        return [int(a) for i in coll for a in _flatten(i)]27    else:28        return [coll]293031def _importSection(obj, filename):32    """ Imports section's syntax into dictionary.33    """34    name = obj.name35    try:36        with open(filename, 'r') as data:37            section = None38            for row in data:39                found = _findall(r'(?<=\- )(.*?)(?=\: -)', row)40                if row in ['\n', '\r\n']:41                    continue42                elif found:43                    section = found[0]44                elif section == name and row[0] != '-':45                    obj._readSection(row)46                else:47                    continue48    except IOError:49        print ('cannot open', filename)505152def _updateFile(orgFile, newFile, name, printData):53    """ Update a section of a VISSIM .INP file.54        Inputs: filename, object type(Inputs, Routing Decision, etc.) and list55        of strings with VISSIM syntax.56        Outputs: new file57    """58    search = '-- ' + name + ': --'59    f = open(orgFile, 'r')60    lines = f.readlines()61    f.close()62    f = open(newFile, 'w')63    startDelete = False64    print ('Writing %s to %s ...' % (name, newFile))65    for line in lines:66        if startDelete is True and line[:3] == '-- ':67            startDelete = False68            f.write('\n\n\n')69        if line[:len(search)] == search:70            startDelete = True71            for newLine in printData:72                f.write(str(newLine) + '\n')73        if startDelete is False:74            f.write(line)75    f.close()767778def _exportSection(obj, filename):79    """ Prepare for export all dictionaries within a given object8081        Input: Dict object82        Output: List of all items for a given class in VISSIM syntax83    """84    first_line = '-- ' + obj.name + ': --\n'85    second_line = '-' * (len(first_line) - 1) + '\n'86    print_data = [first_line + second_line]87    print ('Reading %s ...' % obj.name)88    for value in obj.data.values():89        print_data += obj._output(value)90    print ('Updating %s ...' % obj.name)91    _updateFile(obj.filename, filename, obj.name, print_data)929394def _checkKeyData(obj, key, label):95    """ Checks whether key and label exist96    """97    if key is not None:98        if key not in obj.data:99            raise KeyError('%s not a valid key for object %s' %100                           (key, obj.name))101    if label not in obj.types:102        raise KeyError('%s not a valid label for object %s' %103                       (label, obj.name))104    return True105106107def _getData(obj, key, label):108    """ Returns requested value from vissim object109    """110    _checkKeyData(obj, key, label)111    if key is None:112        new = obj.data[label]113    else:114        new = obj.data[key][label]115    return _copy(new)116117118def _setData(obj, key, label, value):119    """ Sets given value in vissim object120    """121    _checkKeyData(obj, key, label)122    if not isinstance(value, obj.types[label]):123        value = obj.types[label](value)124    if key is None:125        obj.data[label] = value126    else:127        obj.data[key][label] = value128129130def _updateData(obj, key, label, value, pos=None, newKey=None):131    """ Updates vissim object132        Input: object, key, label and value133        Output: adds value to object.134    """135    _checkKeyData(obj, key, label)136    if key is None:137        if (isinstance(obj.data[label], list) is True) and (pos is None):138            obj.data[label].append(value)139            obj.data[label] = list(_flatten(obj.data[label]))140        elif isinstance(obj.data[label], list) and pos:141            obj.data[label].insert(pos, value)142            obj.data[label] = list(_flatten(obj.data[label]))143    else:144        if isinstance(obj.data[key][label], dict):145            obj.data[key][label][newKey] = value146        if (isinstance(obj.data[key][label], list) is True) and (pos is None):147            obj.data[label].append(value)148            obj.data[label] = list(_flatten(obj.data[label]))149        elif isinstance(obj.data[key][label], list) and pos:150            obj.data[label].insert(pos, value)151            obj.data[label] = list(_flatten(obj.data[label]))152153154def _convertType(iterable, newType):155    """ Converts element type within iterable.156    """157    iterType = type(iterable)158    return iterType([newType(i) for i in iterable])159160161class Inputs:162    """ Handles Inputs section of .INP file.163    """164    def __init__(self, filename):165        self.filename = filename166        self.name = 'Inputs'167        self.data = {}168        self.currData = None169        self.types = {'composition': int, 'exact': bool, 'from': float,170                      'input': int, 'label': tuple, 'link': int, 'name': str,171                      'q': float, 'until': float}172        _importSection(self, filename)173174    def get(self, inputNum, label, string=True):175        """ Get value from Input.176            Input: Input number, Value label177            Output: Value178        """179        if string:180            return str(_getData(self, inputNum, label))181        else:182            return _getData(self, inputNum, label)183184    def set(self, inputNum, label, value):185        """ Set value from Input.186            Input: Input number, Value label, value187            Output: Change is made in place188        """189        _setData(self, inputNum, label, value)190191    def getInputNumByLink(self, linkNum):192        """ Get value from Input by link number193            Input: Link number194            Output: List of input numbers195        """196        result = [k for k, v in self.data.items() if v['link'] == linkNum]197        if len(result) == 0:198            raise KeyError('%s not in data' % (linkNum))199        else:200            return result201202    def create(self, linkNum, demand, comp, **kwargs):203        """ Create new Input204            Input: link number, demand, vehicle composition205            Output: Creates Input object206        """207        if self.data.keys():208            num = max(self.data.keys()) + 1209        else:210            num = 1211        inputNum = kwargs.get('input', num)212        self.data[inputNum] = {}213        self.set(inputNum, 'input', inputNum)214        self.set(inputNum, 'q', demand)215        self.set(inputNum, 'link', linkNum)216        self.set(inputNum, 'composition', comp)217        # Default values218        self.set(inputNum, 'name', kwargs.get('name', '""'))219        self.set(inputNum, 'label', kwargs.get('label', ('0.00', '0.00')))220        self.set(inputNum, 'from', kwargs.get('from', '0.0'))221        self.set(inputNum, 'until', kwargs.get('until', '3600.0'))222        self.set(inputNum, 'exact', kwargs.get('exact', False))223224    def _readSection(self, line):225        """ Process the Input section of the INP file.226        """227        if _match('^INPUT\s+\d+', line):228            inputNum = self.types['input'](_findall('INPUT\s+(\d+)', line)[0])229            self.currData = {'input': inputNum}230        elif _match('^\s+NAME', line):231            self.currData['name'] = _findall('NAME\s+(".+"|"")', line)[0]232            self.currData['label'] = _findall('LABEL\s+(-?\d+.\d+)\s(-?\d+.\d+)', line)[0]233        elif _match('^\s+LINK', line):234            self.currData['link'] = _findall('LINK\s+(\d+)', line)[0]235            if _search('EXACT', line):236                self.currData['exact'] = True237                self.currData['q'] = _findall('Q EXACT (.+) COMPOSITION',238                                              line)[0]239            else:240                self.currData['exact'] = False241                self.currData['q'] = _findall('Q (.+) COMPOSITION', line)[0]242            self.currData['composition'] = _findall('COMPOSITION (\d)',243                                                    line)[0]244        elif _match('^\s+TIME', line):245            self.currData['from'] = _findall('FROM (\d+.\d+)', line)[0]246            self.currData['until'] = _findall('UNTIL (\d+.\d+)', line)[0]247            # Last line, create Input object248            self.create(self.currData['link'], self.currData['q'],249                        self.currData['composition'], **self.currData)250        else:251            print ('Non-Input data provided: %s' % line)252253    def _output(self, inputs):254        """ Outputs Inputs syntax to VISSIM.255256        Input: A single Inputs dictionary257        Output: Inputs back into VISSIM syntax258        """259        vissimOut = []260        inputNum = inputs['input']261262        def _out(label, s=True):263            return self.get(inputNum, label, string=s)264        vissimOut.append('INPUT ' + _out('input').rjust(6))265        vissimOut.append('NAME '.rjust(10) + _out('name') + ' LABEL  ' +266                         _out('label', s=False)[0] + ' ' +267                         _out('label', s=False)[1])268        if _out('exact', s=False) is True:269            vissimOut.append('LINK '.rjust(10) + _out('link') + ' Q EXACT ' +270                             _out('q') + ' COMPOSITION ' +271                             _out('composition'))272        else:273            vissimOut.append('LINK '.rjust(10) + _out('link') + ' Q ' +274                             _out('q') + ' COMPOSITION ' + _out('composition'))275        vissimOut.append('TIME FROM '.rjust(15) + _out('from') + ' UNTIL ' +276                         _out('until'))277        return vissimOut278279    def export(self, filename):280        """ Prepare for export all inputs in a given inputs object281282            Input: Inputs object283            Output: List of all inputs in VISSIM syntax284        """285        _exportSection(self, filename)286287288class Links:289    """ Handles Links section of .INP file.290    """291    def __init__(self, filename):292        self.filename = filename293        self.name = 'Links'294        self.data = {}295        self.over = None296        self.currData = None297        self.closed = None298        self.types = {'link': int, 'name': str, 'label': tuple,299                      'behaviortype': int, 'displaytype': int, 'length': float,300                      'lanes': int, 'lane_width': list, 'gradient': float,301                      'cost': float, 'surcharges': list,302                      'segment_length': float, 'evaluation': bool,303                      'from': list, 'over': list, 'to': list, 'closed': dict}304        _importSection(self, filename)305306    def get(self, linkNum, label, string=True):307        """ Get value from Link.308            Input: Link number, Value label309            Output: Value310        """311        if string:312            return str(_getData(self, linkNum, label))313        else:314            return _getData(self, linkNum, label)315316    def set(self, linkNum, label, value):317        """ Set value from Link.318            Input: Link number, Value label, value319            Output: Change is made in place320        """321        _setData(self, linkNum, label, value)322323    def create(self, coordFrom, coordTo, **kwargs):324        if self.data.keys():325            num = max(self.data.keys()) + 1326        else:327            num = 1328        linkNum = kwargs.get('link', num)329        self.data[linkNum] = {}330        self.set(linkNum, 'link', linkNum)331        self.set(linkNum, 'from', coordFrom)332        self.set(linkNum, 'to', coordTo)333        # Default values334        self.set(linkNum, 'name', kwargs.get('name', '""'))335        self.set(linkNum, 'behaviortype', kwargs.get('behaviortype', 1))336        self.set(linkNum, 'cost', kwargs.get('cost', 0.00000))337        self.set(linkNum, 'displaytype', kwargs.get('displaytype', 1))338        self.set(linkNum, 'gradient', kwargs.get('gradient', 0.00000))339        self.set(linkNum, 'label', kwargs.get('label', ('0.00', '0.00')))340        self.set(linkNum, 'lane_width', kwargs.get('lane_width', [3.66]))341        self.set(linkNum, 'lanes', kwargs.get('lanes', 1))342        self.set(linkNum, 'segment_length', kwargs.get('segment_length',343                 10.000))344        self.set(linkNum, 'surcharges', kwargs.get('surcharges',345                 [0.00000, 0.00000]))346        self.set(linkNum, 'evaluation', kwargs.get('evaluation', False))347        self.set(linkNum, 'over', kwargs.get('over', []))348        self.set(linkNum, 'length', kwargs.get('length', 0))349        if self.get(linkNum, 'over') and self.get(linkNum, 'length') == 0:350            x1, y1 = self.get(linkNum, 'from')351            z1 = 0352            length = 0353            for coord in self.get(linkNum, 'over'):354                x2, y2, z2 = _convertType(coord, float)355                dx, dy, dz = x2 - x1, y2 - y1, z2 - z1356                length += _sqrt(dx**2 + dy**2 + dz**2)357                x1, y1, z1 = x2, y2, z2358            self.set(linkNum, 'length', round(length, 3))359        elif self.get(linkNum, 'length') == 0:360            length = round(_sqrt((self.get(linkNum, 'to')[0] -361                           self.get(linkNum, 'from')[0])**2 +362                           (self.get(linkNum, 'to'[1] - self.get(linkNum,363                            'from')[1])**2), 3))364            self.set(linkNum, 'length', length)365366    def _readSection(self, line):367        if _match('^LINK', line):368            linkNum = (self.types['link'](_findall('LINK\s+(\d+)', line)[0]))369            self.currData = {'link': linkNum}370            self.currData['name'] = _findall('NAME\s+(".+"|"")', line)[0]371            self.currData['label'] = (_findall(372                                      'LABEL\s+(-?\d+.\d+)\s(-?\d+.\d+)',373                                      line)[0])374        elif _match('^\s+BEHAVIORTYPE', line):375            self.currData['behaviortype'] = _findall('BEHAVIORTYPE\s+(\d+)',376                                                     line)[0]377            self.currData['displaytype'] = _findall('DISPLAYTYPE\s+(\d+)',378                                                    line)[0]379        elif _match('^\s+LENGTH', line):380            self.currData['length'] = _findall('LENGTH\s+(\d+.\d+)', line)[0]381            self.currData['lanes'] = _findall('LANES\s+(\d)', line)[0]382            width = _findall('LANE_WIDTH\s+(.+)\s+GRADIENT', line)[0]383            self.currData['lane_width'] = _split('\s+', width)384            self.currData['gradient'] = _findall('GRADIENT\s+(-?\d+.\d+)',385                                                 line)[0]386            self.currData['cost'] = _findall('COST\s+(\d+.\d+)', line)[0]387            self.currData['surcharges'] = _findall('SURCHARGE\s+(\d+.\d+)',388                                                   line)389            self.currData['segment_length'] = (_findall(390                                               'SEGMENT LENGTH\s+(\d+.\d+)',391                                               line)[0])392            if _search('EVALUATION', line):393                self.currData['evaluation'] = True394            else:395                self.currData['evaluation'] = False396        elif _match('^\s+FROM', line):397            self.currData['from'] = _findall('(-?\d+.\d+)', line)398        elif _match('^\s+OVER', line):399            if 'over' not in self.currData:400                self.currData['over'] = []401            self.currData['over'] += _findall('OVER (-?\d+.\d+) (-?\d+.\d+) (-?\d+.\d+)', line)402        elif _match('^\s+TO', line):403            self.currData['to'] = _findall('(-?\d+.\d+)', line)404            self.create(self.currData['from'], self.currData['to'], **self.currData)405        elif _match('^\s+CLOSED', line):406            self.currData['closed'] = {}407        elif 'closed' in self.currData and _match('^LANE', line):408            lane = _findall('^LANE\s+(\d+)', line)409            veh_classes = _findall('VEHICLE_CLASSES (.+)', line)410            self.currData['closed'][lane] = _split('\s', veh_classes)411            self.set(self.currData['link'], 'closed', self.currData['closed'])412        else:413            print ('Non-link data provided: %s' % line)414415    def _output(self, links):416        """ Outputs Links syntax to VISSIM.417418        Input: A single links dictionary419        Output: Route decisions back into VISSIM syntax420        """421        vissimOut = []422        linkNum = links['link']423424        def _out(label, s=True):425            a = self.get(linkNum, label, string=s)426            return str(a)427428        vissimOut.append('LINK ' + _out('link').rjust(6) + ' NAME ' +429                         _out('name') + ' LABEL ' +430                         _out('label', s=False)[0] + ' ' +431                         _out('label', s=False)[1])432        vissimOut.append('BEHAVIORTYPE '.rjust(15) + _out('behaviortype').433                         rjust(5) + ' DISPLAYTYPE' + _out('displaytype').434                         rjust(5))435        laneWidth = ''436        if len(_out('lane_width', s=False)) > 1:437            for width in _out('lane_width', s=False):438                laneWidth += width.rjust(5)439        else:440            laneWidth = _out('lane_width', s=False)[0].rjust(5)441        evaluation = 'EVALUATION' if _out('evaluation', s=False) else ''442        vissimOut.append('LENGTH '.rjust(9) + _out('length').rjust(8) +443                         ' LANES ' + _out('lanes').rjust(2) +444                         ' LANE_WIDTH ' + laneWidth + ' GRADIENT ' +445                         _out('gradient').ljust(10) + ' COST ' +446                         _out('cost').ljust(7) + ' SURCHARGE ' +447                         _out('surcharges', s=False)[0] + ' SURCHARGE ' +448                         _out('surcharges', s=False)[1] + ' SEGMENT LENGTH ' +449                         _out('segment_length').rjust(8) +450                         evaluation)451        vissimOut.append('FROM '.rjust(7) + _out('from', s=False)[0] + ' ' +452                         _out('from', s=False)[1])453454        print (vissimOut)455        print(_out('from', s=False))456        print (_out('over', s=False))457        print(_out('to', s=False))458459        if _out('over', s=False):460            overStr = ''461462            for no, i in enumerate(_out('over', s=False)):463                print (str(no) + ": " + str(i))464                # overStr += '  OVER ' + i[0] + ' ' + i[1] + ' ' + i[2]465                if no == 30:466                    raise ("Stop here!")467            vissimOut.append(overStr)468        vissimOut.append('TO '.rjust(5) + _out('to', s=False)[0].rjust(10) +469                         ' ' + _out('to', s=False)[1])470        return vissimOut471472    def export(self, filename):473        """ Prepare for export all links in a given links object474475            Input: Links object476            Output: List of all links in VISSIM syntax477        """478        _exportSection(self, filename)479480481class Connector:482    """ Handles Connector section of .INP file.483    """484    def __init__(self, filename):485        self.filename = filename486        self.name = 'Connectors'487        self.data = {}488        self.currData = None489        self.curr_lane = None490        self.types = {'connector': int, 'name': str, 'label': tuple,491                      'from': int, 'from_lanes': list, 'from_at': float,492                      'over': list, 'to': int, 'to_lanes': list,493                      'to_at': float, 'behavior_type': int,494                      'display_type': int, 'dx_emerg_stop': float,495                      'dx_lane_change': float, 'gradient': float,496                      'cost': float, 'surcharges': list,497                      'segment_length': float, 'animation': bool,498                      'nolanechange': dict}499        _importSection(self, filename)500        self.links = Links(self.filename)501502    def get(self, connNum, label, string=True):503        """ Get value from Connector.504            Input: Connector number, Value label505            Output: Value506        """507        if string:508            return str(_getData(self, connNum, label))509        else:510            return _getData(self, connNum, label)511512    def set(self, connNum, label, value):513        """ Set value from Connector.514            Input: Connector number, Value label, value515            Output: Change is made in place516        """517        _setData(self.data, connNum, label, value)518519    def create(self, fromLink, toLink, **kwargs):520        if self.data.keys():521            num = max(self.data.keys()) + 1522        else:523            num = 1524        connNum = kwargs.get('connector', num)525        self.data[connNum] = {}526        connector = self.data[connNum]527        self.set(connNum, 'connector', connNum)528        self.set(connNum, 'from', fromLink)529        self.set(connNum, 'to', toLink)530        # Default values531        self.set(connNum, 'label', kwargs.get('label', ('0.00', '0.00')))532        self.set(connNum, 'from_lanes', kwargs.get('from_lanes', 1))533        self.set(connNum, 'from_at', kwargs.get('from_at',534                 self.links.get(fromLink, 'length')))535        # Calculate default spline points between from link and to link:536        over1 = self.links.get(fromLink, 'to').append('0.000')537        over4 = self.links.get(toLink, 'from').append('0.000')538        if over4[0] == over1[0] and over4[1] == over1[1]:539            over1[1] = over1[1] + 0.001540            over2 = [over4[0] + 0.001, over4[1], over4[2]]541            over3 = [_median([over2[0], over4[0]]), _median([over2[1],542                     over4[1]]), _median([over2[2], over4[2]])]543        else:544            over2 = [_median([over4[0], over1[0]]), _median([over4[1],545                     over1[1]]), _median([over4[2], over1[2]])]546            over3 = [_median([over2[0], over4[0]]), _median([over2[1],547                     over4[1]]), _median([over2[2], over4[2]])]548        self.set(connNum, 'over', kwargs.get('over',549                 [over1, over2, over3, over4]))550        self.set(connNum, 'name', kwargs.get('name', '""'))551        self.set(connNum, 'to_lanes', kwargs.get('to_lanes', ['1']))552        self.set(connNum, 'to_at', kwargs.get('to_at', '0.000'))553        self.set(connNum, 'behaviortype', kwargs.get('behaviortype', 1))554        self.set(connNum, 'displaytype', kwargs.get('displaytype', 1))555        self.set(connNum, 'dx_emerg_stop', kwargs.get('dx_emerg_stop', 4.999))556        self.set(connNum, 'dx_lane_change', kwargs.get('dx_lane_change',557                                                       200.010))558        self.set(connNum, 'gradient', kwargs.get('gradient', 0.00000))559        self.set(connNum, 'cost', kwargs.get('cost', 0.00000))560        self.set(connNum, 'surcharges', kwargs.get('surcharges',561                                                   ['0.00000', '0.00000']))562        self.set(connNum, 'segment_length', kwargs.get('segment_length',563                 10.000))564        self.set(connNum, 'animation', kwargs.get('animation', True))565        self.set(connNum, 'nolanechange', kwargs.get('nolanechange', None))566567    def _readSection(self, line):568        if _match('^CONNECTOR', line):569            # Connector number is dictionary key570            conn = _findall('^CONNECTOR\s+(\d+)', line)[0]571            self.data[conn] = {}572            self.currData = self.data[conn]573            self.currData['connector'] = conn574            self.currData['name'] = _findall('NAME\s+(".+"|"")', line)[0]575            self.currData['label'] = _findall('LABEL\s+(-?\d+.\d+)\s(-?\d+.\d+)', line)[0]576        elif _match('^\s+FROM', line):577            self.currData['from'] = _findall('LINK\s+(\d+)', line)[0]578            lanes = _findall('LANES\s(.+)\sAT', line)[0]579            self.currData['from_lanes'] = _split('\s+', lanes)580            self.currData['from_at'] = _findall('AT\s+(\d+.\d+)', line)[0]581        elif _match('^\s+OVER', line):582            if 'over' not in self.currData:583                self.currData['over'] = []584            self.currData['over'] += _findall('OVER (-?\d+.\d+) (-?\d+.\d+) (-?\d+.\d+)', line)585        elif _match('^\s+TO', line):586            self.currData['to'] = _findall('LINK\s+(\d+)', line)[0]587            lanes = _findall('LANES\s(.+)\sAT', line)[0]588            self.currData['to_lanes'] = _split('\s+', lanes)589            self.currData['to_at'] = _findall('AT\s+(\d+.\d+)', line)[0]590            self.currData['behaviortype'] = _findall('BEHAVIORTYPE\s+(\d+)',591                                                     line)[0]592            self.currData['displaytype'] = _findall('DISPLAYTYPE\s+(\d+)',593                                                    line)[0]594        elif _match('^\s+DX_EMERG_STOP', line):595            self.currData['dx_emerg_stop'] = _findall('DX_EMERG_STOP\s+(\d+.\d+)', line)[0]596            self.currData['dx_lane_change'] = _findall('DX_LANE_CHANGE\s+(\d+.\d+)', line)[0]597        elif _match('^\s+GRADIENT', line):598            self.currData['gradient'] = _findall('GRADIENT\s+(-?\d+.\d+)',599                                                 line)[0]600            self.currData['cost'] = _findall('COST\s+(\d+.\d+)', line)[0]601            self.currData['surcharges'] = _findall('SURCHARGE\s+(\d+.\d+)',602                                                   line)603        elif _match('^\s+SEGMENT', line):604            self.currData['segment_length'] = _findall('LENGTH\s+(\d+.\d+)',605                                                       line)[0]606            if _search('NONE ANIMATION', line):607                self.currData['animation'] = False608            else:609                self.currData['animation'] = True610        elif _search('NOLANECHANGE', line):611            self.currData['nolanechange'] = {}612            lanes = _findall('LANE\s+(\d+) (\w+) (\w+)', line)613            for lane, o, d in lanes:614                self.currData['nolanechange'][lane] = {'from': o, 'to': d}615        else:616            print ('Non-connector data provided: %s' % line)617618    def _output(self, connector):619        """ Outputs connector syntax to VISSIM.620621        Input: A single connector dictionary622        Output: connector back into VISSIM syntax623        """624        vissimOut = []625        connNum = connector['connector']626627        def _out(label, s=True):628            return self.get(connNum, label, string=s)629        vissimOut.append('CONNECTOR ' + _out('connector') +630                         ' NAME ' + _out('name') + ' LABEL ' +631                         _out('label')[0] + ' ' + _out('label')[1])632        fromLanesStr = ''633        for i in _out('from_lanes', s=False):634            fromLanesStr += i + ' '635        vissimOut.append('FROM LINK '.rjust(12) + _out('from') +636                         ' LANES ' + fromLanesStr + 'AT ' + _out('from_at'))637        overStr = ''638        for i in _out('over', s=False):639            overStr += '  OVER ' + i[0] + ' ' + i[1] + ' ' + i[2]640        vissimOut.append(overStr)641        toLanesStr = ''642        for i in _out('to_lanes'):643            toLanesStr += i + ' '644        vissimOut.append('TO LINK '.rjust(10) + _out('to') +645                         ' LANES '.rjust(7) + toLanesStr + 'AT ' +646                         _out('to_at').ljust(6) + ' BEHAVIORTYPE ' +647                         _out('behaviortype') + ' DISPLAYTYPE ' +648                         _out('displaytype') + ' ALL')649        vissimOut.append('DX_EMERG_STOP '.rjust(16) + _out('dx_emerg_stop') +650                         ' DX_LANE_CHANGE ' + _out('dx_lane_change'))651        vissimOut.append('GRADIENT '.rjust(11) + _out('gradient') +652                         ' COST ' + _out('cost') + ' SURCHARGE ' +653                         _out('surcharges')[0] + ' SURCHARGE ' +654                         _out('surcharges')[1])655        if connector['animation'] is False:656            vissimOut.append('SEGMENT LENGTH '.rjust(17) +657                             _out('segment_length') + ' NONE ANIMATION')658        else:659            vissimOut.append('SEGMENT LENGTH '.rjust(17) +660                             _out('segment_length') + ' ANIMATION')661        return vissimOut662663    def export(self, filename):664        """ Prepare for export all connector lots in a given connector object665666            Input: connector object667            Output: List of all connector lots in VISSIM syntax668        """669        _exportSection(self, filename)670671672class Parking:673    """ Handles Parking section of .INP file.674    """675    def __init__(self, filename):676        self.filename = filename677        self.name = 'Parking Lots'678        self.data = {}679        self.currData = None680        _importSection(self, filename)681682    def create(self, linksobj, link, length, at, lane, **kwargs):683        parking_num = int(kwargs.get('num', max(self.data.keys())+1))684        self.data[parking_num] = {}685        parking = self.data[parking_num]686        parking['parking'] = parking_num687        parking['lane'] = lane688        parking['at'] = at689        parking['position_link'] = link690        parking['length'] = length691        # Default values692        parking['name'] = kwargs.get('name', '""')693        parking['label'] = kwargs.get('label', ['0.000', '0.000'])694        parking['spaces_length'] = kwargs.get('spaces_length', '6.000')695        parking['zones'] = kwargs.get('zones', '""')696        parking['fraction'] = kwargs.get('fraction', '1.000')697        parking['capacity'] = kwargs.get('capacity', '100')698        parking['occupancy'] = kwargs.get('occupancy', '0')699        parking['desired_speed'] = kwargs.get('desired_speed', '999')700        parking['open_hours'] = kwargs.get('open_hours', ('0', '99999'))701        parking['max_time'] = kwargs.get('max_time', '99999')702        parking['flat_fee'] = kwargs.get('flat_fee', '0.0')703        parking['fee_per_hour'] = kwargs.get('fee_per_hour', '0.0')704        parking['attraction'] = kwargs.get('attraction', '0.0 0.0')705        parking['composition'] = kwargs.get('composition', '1')706707    def _readSection(self, line):708        if _match('^\s+PARKING_LOT', line):709            # Parking lot number is dictionary key710            parking = _findall('PARKING_LOT\s+(\d+)')[0]711            self.data[parking] = {}712            self.currData = self.data[parking]713            self.currData['parking'] = parking714            self.currData['name'] = _findall('NAME\s+(".+"|"")', line)[0]715            self.currData['label'] = _findall('LABEL\s+(-?\d+.\d+)\s(-?\d+.\d+)', line)[0]716        elif _match('^\s+PARKING_SPACES', line):717            self.currData['spaces_length'] = _findall('LENGTH\s+(\d+.\d+)', line)[0]718        elif _match('^\s+ZONES', line):719            self.currData['zones'] = _findall('ZONES\s+(\d+)', line)[0]720            self.currData['fraction'] = _findall('FRACTION\s+(\d+.\d+), line')[0]721        elif _match('^\s+POSITION', line):722            self.currData['position_link'] = _findall('POSITION LINK\s+(\d+)', line)[0]723            self.currData['at'] = _findall('AT\s+(\d+.\d+)', line)[0]724            if _match('POSITION LINK \d+ LANE \d+', line):725                self.currData['lane'] = _findall('LANE (\d+)', line)[0]726        elif _match('^\s+LENGTH', line):727            self.currData['length'] = _findall('LENGTH\s+(\d+.\d+)', line)[0]728        elif _match('^\s+CAPACITY', line):729            self.currData['capacity'] = _findall('CAPACITY\s+(\d+)', line)[0]730        elif _match('^\s+OCCUPANCY', line):731            self.currData['occupancy'] = _findall('OCCUPANCY\s+(\d+)', line)[0]732        elif _match('^\s+DEFAULT', line):733            self.currData['desired_speed'] = _findall('DESIRED_SPEED\s+(\d+)', line)[0]734        elif _match('^\s+OPEN_HOURS', line):735            self.currData['open_hours'] = _findall('FROM\s+(\d+)\s+UNTIL\s+(\d+)', line)736        elif _match('^\s+MAX_TIME', line):737            self.currData['max_time'] = _findall('MAX_TIME\s+(\d+)', line)[0]738        elif _match('^\s+FLAT_FEE', line):739            self.currData['flat_fee'] = _findall('FLAT_FEE\s+(\d+.\d+)', line)[0]740        elif _match('^\s+FEE_PER_HOUR', line):741            self.currData['fee_per_hour'] = _findall('FEE_PER_HOUR\s+(\d+.\d+)', line)[0]742        elif _match('^\s+ATTRACTION', line):743            if 'spaces_length' in self.currData:744                self.currData['attraction'] = _findall('ATTRACTION\s+(\d+.\d+)\s(\d+.\d+)', line)745            else:746                self.currData['attraction'] = _findall('ATTRACTION\s+(\d+.\d+)', line)747        elif _match('^\s+COMPOSITION', line):748            self.currData['composition'] = _findall('COMPOSITION\s+(\d+)', line)[0]749        else:750            print ('Non-parking data provided: %s' % line)751752    def _output(self, parking):753        """ Outputs Parking syntax to VISSIM.754755        Input: A single parking dictionary756        Output: Parking back into VISSIM syntax757        """758        vissimOut = []759        vissimOut.append('PARKING_LOT ' + str(parking['parking']) + ' NAME ' +760                          parking['name'] + ' LABEL ' + parking['label'][0] +761                          ' ' + parking['label'][1])762        if 'spaces_length' in parking:763            vissimOut.append('PARKING_SPACES LENGTH '.rjust(24) + parking764                              ['spaces_length'])765        vissimOut.append('ZONES '.rjust(8) + parking['zones'].rjust(6) +766                          ' FRACTION ' + parking['fraction'].rjust(7))767        if 'lane' in parking:768            vissimOut.append('POSITION LINK '.rjust(16) + str(parking[769                              'position_link']) + ' LANE ' + str(parking770                              ['lane']) + ' AT ' + str(parking['at']))771        else:772            vissimOut.append('POSITION LINK '.rjust(16) + str(parking773                              ['position_link']) + ' AT ' + str(parking['at']))774        vissimOut.append('LENGTH '.rjust(9) + str(parking['length']).rjust(9))775        vissimOut.append('CAPACITY   '.rjust(13) + parking['capacity'])776        vissimOut.append('OCCUPANCY '.rjust(12) + parking['occupancy'])777        vissimOut.append('DEFAULT DESIRED_SPEED '.rjust(24) + parking778                          ['desired_speed'])779        vissimOut.append('OPEN_HOURS  FROM '.rjust(19) + parking['open_hours']780                          [0].ljust(2) + ' UNTIL ' + parking['open_hours'][1])781        vissimOut.append('MAX_TIME '.rjust(11) + parking['max_time'])782        vissimOut.append('FLAT_FEE '.rjust(11) + parking['flat_fee'])783        vissimOut.append('FEE_PER_HOUR '.rjust(15) + parking['fee_per_hour'])784        if len(parking['attraction']) > 1:785            vissimOut.append('ATTRACTION '.rjust(13) +786                              parking['attraction'][0] + ' ' +787                              parking['attraction'][1])788        else:789            vissimOut.append('ATTRACTION '.rjust(13) +790                              parking['attraction'][0])791        if 'composition' in parking:792            vissimOut.append('COMPOSITION '.rjust(14) + parking793                              ['composition'])794        return vissimOut795796    def __export(self, filename):797        """ Prepare for export all parking lots in a given parking object798799            Input: Parking object800            Output: List of all parking lots in VISSIM syntax801        """802        _exportSection(self, filename)803804805class Transit:806    """ Handles Transit section of .INP file.807    """808    def __init__(self, filename):809        self.filename = filename810        self.name = 'Public Transport'811        self.data = {}812        self.currData = None813        _importSection(self, filename)814815    def create(self, link, dest_link, at, desired_speed, vehicle_type,816               **kwargs):817        transit_num = kwargs.get('num', max(self.data.keys() or [0]) + 1)818        self.data[transit_num] = {}819        transit = self.data[transit_num]820        transit['line'] = str(transit_num)821        transit['link'] = str(link)822        transit['at'] = str(at)823        transit['destination_link'] = str(dest_link)824        transit['desired_speed'] = str(desired_speed)825        transit['vehicle_type'] = str(vehicle_type)826        # Default values827        transit['anm'] = kwargs.get('anm', '""')828        transit['name'] = kwargs.get('name', '""')829        transit['route'] = kwargs.get('route', '0')830        transit['priority'] = kwargs.get('priority', '0')831        transit['length'] = kwargs.get('length', '0')832        transit['mdn'] = kwargs.get('mdn', '0')833        transit['pt'] = kwargs.get('pt', False)834        transit['color'] = kwargs.get('color', 'CYAN')835        transit['time_offset'] = kwargs.get('time_offset', '0.0')836        transit['start_times'] = kwargs.get('start_times', [])837838    def _readSection(self, line):839        """ Process the Transit Decision section of the INP file840        """841        if line[0] == "LINE":842            # Dictionary key is the line number843            self.data[line[1]] = {}844            self.currData = self.data[line[1]]845            self.currData['line'] = line[1]846            self.currData['name'] = line[3]847            self.currData['route'] = line[7]848            self.currData['priority'] = line[9]849            self.currData['length'] = line[11]850            self.currData['mdn'] = line[13]851            if len(line) == 14:852                self.currData['pt'] = True853        elif line[0] == "ANM_ID":854            self.currData['link'] = line[4]855            self.currData['desired_speed'] = line[6]856            self.currData['vehicle_type'] = line[8]857        elif line[0] == "COLOR":858            self.currData['color'] = line[1]859            self.currData['time_offset'] = line[3]860        elif line[0] == "DESTINATION":861            self.currData['destination_link'] = line[2]862            self.currData['at'] = line[4]863        elif line[0] == "START_TIMES":864            self.currData['start_times'] = []865            num = (len(line)-1)/5866            for i in range(num):867                self.currData['start_times'].append([line[1+(5*i)], line868                                                     [3+(5*i)], line[5+(5*i)]])869        elif line[1] == "COURSE":870            num = (len(line)/5)871            for i in range(num):872                self.currData['start_times'].append([line[(5*i)], line873                                                     [2+(5*i)], line[4+(5*i)]])874        else:875            print ('Non-transit data provided: %s' % line)876877    def _output(self, transit):878        """ Outputs transit Decision syntax to VISSIM.879880        Input: A single transit decision dictionary881        Output: transit decisions back into VISSIM syntax882        """883        vissimOut = []884        pt = ''885        if transit['pt'] == True:886            pt = ' PT_TELE'887        vissimOut.append(str('LINE ' + transit['line'].rjust(4) + ' NAME ' +888                              transit['name'] + '  LINE ' + transit['line'].889                              rjust(3) + '  ROUTE ' + transit['route'].rjust(3)890                              + '    PRIORITY ' + transit['priority'] +891                              '  LENGTH ' + transit['length'] + '  MDN ' +892                              transit['mdn']) + pt + '\n')893        vissimOut.append(str('ANM_ID '.rjust(12) + transit['anm'] +894                              ' SOURCE    LINK ' + transit['link'] +895                              ' DESIRED_SPEED ' + transit['desired_speed'] +896                              ' VEHICLE_TYPE ' + transit['vehicle_type']))897        vissimOut.append(str('COLOR '.rjust(24) + transit['color'] +898                              ' TIME_OFFSET ' + transit['time_offset'].899                              rjust(6)))900        vissimOut.append(str('DESTINATION    LINK '.rjust(32) + transit901                              ['destination_link'] + ' AT ' + transit['at'].902                              rjust(8)))903        time_str = 'START_TIMES '.rjust(24)904        count = 1905        for i in transit['start_times']:906            time_str += str(i[0] + ' COURSE ' + i[1] + ' OCCUPANCY ' + i[2] +907                            ' ')908            if count % 5 == 0:909                time_str += '\n'910            count += 1911        if len(transit['start_times']) > 0:912            vissimOut.append(time_str)913        return vissimOut914915    def export(self, filename):916        """ Prepare for export all transit routes in a given transit object917918            Input: transit object919            Output: List of all transit lots in VISSIM syntax920        """921        _exportSection(self, filename)922923924class Routing:925    """ Handles Routing Decision section of .INP file.926    """927    def __init__(self, filename):928        self.filename = filename929        self.name = 'Routing Decisions'930        self.data = {}931        self.currData = None932        self.destinationLink = None933        self.atLink = None934        self.currRouteNum = None935        self.currRoute = None936        self.over = None937        self.types = {'name': str, 'route': dict, 'number': int,938                      'label': tuple, 'link': int, 'at': float, 'time': list,939                      'vehicle_classes': int, 'PT': int, 'alternatives': bool}940        _importSection(self, filename)941942    class Route:943        """ Individual routes within a given Route Decisions944        """945        def __init__(self, routeNum, destinationLink, atLink, fraction):946            self.name = 'Route'947            self.number = routeNum948            self.types = {'at': float, 'fraction': list, 'link': int,949                          'number': int, 'over': list}950            self.data = {'number': self.types['number'](routeNum),951                         'link': self.types['link'](destinationLink),952                         'at': self.types['at'](atLink),953                         'fraction': self.types['fraction'](fraction)}954955        def get(self, label, string=True):956            """ Get value from Route.957                Input: Route number, Value label958                Output: Value959            """960            if string:961                return str(_getData(self, None, label))962            else:963                return _getData(self, None, label)964965        def set(self, label, value):966            """ Set value from Route.967                Input: Route number, Value label, value968                Output: Change is made in place969            """970            _setData(self, None, label, value)971972        def update(self, label, value, pos=None):973            """ Update list with new value.974                Input: label and value975                Output: Value is appended to data976            """977            _updateData(self, None, label, value, pos=pos)978979        def output(self):980            """ Outputs Route syntax to VISSIM.981            """982            vissimOut = []983            routeNum = self.data['number']984985            def _out(label, s=True):986                return self.get(label, string=s)987            vissimOut.append('ROUTE '.rjust(11) + _out('number').rjust(6) +988                             ' DESTINATION LINK' + _out('link').rjust(6) +989                             ' AT' + _out('at').rjust(9))990            fractionStr = ''991            for j in _out('fraction', s=False):992                fractionStr += 'FRACTION '.rjust(16) + j993            vissimOut.append(fractionStr)994            # Sometimes the route ends on the same link it began:995            if not _out('over', s=False):996                return vissimOut997            else:998                for count, j in enumerate(_out('over', s=False)):999                    if count == 0:1000                        overStr = 'OVER '.rjust(12)1001                        overStr += str(j)1002                    elif count == len(_out('over', s=False)) - 1:1003                        overStr += str(j).rjust(6)1004                        vissimOut.append(overStr)1005                        break1006                    elif (count + 1 % 10) == 0:1007                        overStr += str(j).rjust(6)1008                        vissimOut.append(overStr)1009                        overStr = ' ' * 111010                    else:1011                        overStr += str(j).rjust(6)1012                    if len(_out('over', s=False)) == 1:1013                        vissimOut.append(overStr)1014                return vissimOut10151016    def getRoute(self, decnum, routenum=None):1017        """ Get route objects from a given routing decision number.1018            Input: Routing decision number, route number (optional)1019            Output: If route number is given, return the route object,1020            otherwise return all route objects for the given decision.1021        """1022        if isinstance(routenum, str) is False:1023            routenum = str(routenum)1024        if isinstance(decnum, str) is False:1025            decnum = str(decnum)1026        if routenum is None:1027            _getData(self.data, decnum, 'route').keys()1028        elif decnum not in self.data:1029            raise KeyError('%s not in data' % (decnum))1030        elif routenum not in self.data[decnum]:1031            raise KeyError('%s not in routing decision' % (routenum))1032        else:1033            return self.data[decnum]['route'][routenum]10341035    def get(self, decNum, label, string=True):1036        """ Get value from Routing data.1037            Input: Routing decision number, Value label1038            Output: Value1039        """1040        if string:1041            return str(_getData(self, decNum, label))1042        else:1043            return _getData(self, decNum, label)10441045    def set(self, decNum, label, value):1046        """ Set value from Routing data.1047            Input: Routing decision number, Value label, value1048            Output: Change is made in place1049        """1050        _setData(self, decNum, label, value)10511052    def update(self, decNum, label, key, value):1053        """ Update dict with new key and value.1054            Input: Routing decision number, key, value1055            Output: Change is made in place1056        """1057        _updateData(self, decNum, label, value, newKey=key)10581059    def create(self, startLink, startAt, vehClass, **kwargs):1060        if self.data.keys():1061            num = max(self.data.keys()) + 11062        else:1063            num = 11064        decNum = kwargs.get('number', num)1065        self.data[decNum] = {}1066        self.set(decNum, 'number', decNum)1067        self.set(decNum, 'link', startLink)1068        self.set(decNum, 'at', startAt)1069        self.set(decNum, 'vehicle_classes', vehClass)1070        # Default values1071        self.set(decNum, 'name', kwargs.get('name', '""'))1072        self.set(decNum, 'label', kwargs.get('label', ('0.00', '0.00')))1073        self.set(decNum, 'time', kwargs.get('time', [0.0000, 99999.0000]))1074        self.set(decNum, 'route', kwargs.get('route', {}))1075        self.set(decNum, 'alternatives', kwargs.get('alternatives', False))10761077    def _readSection(self, line):1078        """ Process the Route Decision section of the INP file1079        """1080        if _match('^ROUTING_DECISION', line):1081            # Reset from previous routes1082            self.currRoute = None1083            decNum = (self.types['number'](_findall(1084                      'ROUTING_DECISION\s+(\d+)', line)[0]))1085            # Routing decision number is dict key1086            self.currData = {'number': decNum, 'route': {}}1087            self.currData['name'] = _findall('NAME\s+(".+"|"")', line)[0]1088            self.currData['label'] = _findall('LABEL\s+(-?\d+.\d+)\s(-?\d+.\d+)', line)[0]1089        elif _match('^\s+LINK', line):1090            self.currData['link'] = _findall('LINK\s+(\d+)', line)[0]1091            self.currData['at'] = _findall('AT\s+(\d+.\d+)', line)[0]1092        elif _match('^\s+TIME', line):1093            self.currData['time'] = _findall('FROM\s+(\d+.\d+)\s+UNTIL\s+(\d+.\d+)', line)1094        elif _match('^\s+FROM', line):1095            self.currData['time'].append(_findall('FROM\s+(\d+.\d+)\s+UNTIL\s+(\d+.\d+)', line))1096        elif _match('^\s+VEHICLE_CLASSES', line):1097            self.currData['vehicle_classes'] = _findall('VEHICLE_CLASSES\s+(\d+)', line)[0]1098            self.create(self.currData['link'], self.currData['at'], self.currData['vehicle_classes'], **self.currData)1099        elif _match('^\s+PT', line):1100            self.currData['PT'] = _findall('PT\s+(\d+)', line)[0]1101            self.set(self.currData['number'], 'PT', self.currData['PT'])1102        elif _match('^\s+ALTERNATIVES', line):1103            self.set(self.currData['number'], 'alternatives', True)1104        elif _match('^\s+ROUTE', line):1105            self.over = False1106            # Reset the variables from previous route1107            self.currRouteNum = int(_findall('ROUTE\s+(\d+)', line)[0])1108            self.destinationLink = _findall('LINK\s+(\d+)', line)[0]1109            self.atLink = _findall('AT\s+(\d+.\d+)', line)[0]1110        elif _match('^\s+FRACTION', line):1111            currFraction = _findall('FRACTION\s+(\d+.\d+)', line)1112            self.currRoute = self.Route(self.currRouteNum,1113                                        self.destinationLink, self.atLink,1114                                        currFraction)1115            self.update(self.currData['number'], 'route', self.currRouteNum,1116                        self.currRoute)1117        elif _match('^\s+OVER', line):1118            self.over = True1119            self.currRoute.set('over', _findall('(\d+)',1120                               line))1121        elif self.over is True:1122            self.currRoute.update('over', _findall('(\d+)', line))1123        else:1124            print ('Non-routing data provided: %s' % line)11251126    def _output(self, routing):1127        """ Outputs Route Decision syntax to VISSIM.1128        """1129        decNum = routing['number']1130        vissimOut = []11311132        def _out(label, s=True):1133            return self.get(decNum, label, string=s)1134        vissimOut.append(str('ROUTING_DECISION ' + _out('number').ljust(4) +1135                             ' NAME ' + _out('name') + ' LABEL ' +1136                         _out('label', s=False)[0] + ' ' +1137                         _out('label', s=False)[1]))1138        vissimOut.append(str('LINK '.rjust(10) + _out('link') + 'AT '.rjust1139                             (5) + _out('at')))1140        timeStr = 'TIME'.rjust(9)1141        for i in _out('time', s=False):1142            timeStr += str('  FROM ' + str(i[0]) + ' UNTIL ' + str(i[1]))1143        vissimOut.append(timeStr)1144        if _out('vehicle_classes'):1145            vissimOut.append('VEHICLE_CLASSES '.rjust(21) +1146                             _out('vehicle_classes'))1147        elif _out('PT'):1148            vissimOut.append('PT '.rjust(21) + _out('PT'))1149        for route in self.get(decNum, 'route', string=False).values():1150            vissimOut += route.output()1151        return vissimOut11521153    def export(self, filename):1154        """ Prepare for export all routes in a given route object11551156            Input: Route object1157            Output: List of all routes in VISSIM syntax1158        """1159        _exportSection(self, filename)116011611162class Node:1163    """ Handles Node section of .INP file.1164    """1165    def __init__(self, filename):1166        self.filename = filename1167        self.name = 'Nodes'1168        self.data = {}1169        self.curr_node_num = None1170        self.curr_node = None1171        self.node = None1172        _importSection(self, filename)11731174    def _readSection(self, line):1175        if line[0] == 'NODE':1176            self.curr_node_num = int(line[1])1177            self.data[self.curr_node_num] = {}1178            self.curr_node = self.data[self.curr_node_num]1179            self.curr_node['node'] = self.curr_node1180            self.curr_node['name'] = line[3]1181            self.curr_node['label'] = [line[5], line[6]]1182        elif line[0] == 'EVALUATION':1183            self.curr_node['evaluation'] = line[1]1184        elif line[0] == 'NETWORK_AREA':1185            self.curr_node['network_area'] = line[1]1186            self.curr_node['over'] = []1187            overs = int(line[1])1188            for num in range(overs):1189                self.curr_node['over'].append((line[(num*2)+2],1190                                              line[(num*2)+3]))1191        else:1192            print ('Non-node data provided: %s' % line)11931194    def _output(self, node):1195        """ Outputs node syntax to VISSIM.11961197        Input: A single node dictionary1198        Output: node back into VISSIM syntax1199        """1200        vissimOut = []1201        vissimOut.append('NODE ' + str(node['node']) + ' NAME ' + node['name']1202                          + ' LABEL ' + node['label'][0] + ' ' + node['label']1203                          [1])1204        vissimOut.append('EVALUATION '.rjust(13) + node['evaluation'])1205        over_str = ''1206        over_count = 01207        if 'over' in node:1208            for i in node['over']:1209                over_str += '  ' + str(i[0]) + ' ' + str(i[1])1210                over_count += 11211            vissimOut.append('NETWORK_AREA '.rjust(15) + str(over_count) +1212                              over_str)1213        elif 'links' in node:1214            for i in node['links']:1215                over_str += '\nLINK '.rjust(10) + str(i).rjust(10)1216            vissimOut.append('NETWORK_AREA'.rjust(16) + over_str)1217        return vissimOut12181219    def export(self, filename):1220        """ Prepare for export all node lots in a given node object12211222            Input: node object1223            Output: List of all node lots in VISSIM syntax1224        """1225        _exportSection(self, filename)12261227    def createArea(self, area, **kwargs):1228        if 'num' in kwargs:1229            node_num = int(kwargs['num'])1230        elif len(self.data.keys()) == 0:1231            node_num = 11232        else:1233            node_num = max(self.data.keys())+11234        self.data[node_num] = {}1235        node = self.data[node_num]1236        node['node'] = node_num1237        node['over'] = area1238        node['network_area'] = len(area)1239        # Default values1240        node['name'] = '""'1241        node['label'] = ['0.00', '0.00']1242        node['evaluation'] = 'NO'1243        # User defined changes to the default values1244        for name, value in kwargs.items():1245            node[name] = value12461247    def createLink(self, link, **kwargs):1248        if 'num' in kwargs:1249            node_num = int(kwargs['num'])1250        elif len(self.data.keys()) == 0:1251            node_num = 11252        else:1253            node_num = max(self.data.keys())+11254        self.data[node_num] = {}1255        node = self.data[node_num]1256        node['node'] = node_num1257        node['links'] = link1258        # Default values1259        node['name'] = '""'1260        node['label'] = ['0.00', '0.00']1261        node['evaluation'] = 'NO'1262        # User defined changes to the default values1263        for name, value in kwargs.items():
...wml.py
Source:wml.py  
1from owslib.etree import etree2from owslib.util import nspath, testXMLValue, openURL3from owslib.util import xml_to_dict as _xml_to_dict4from datetime import datetime5from dateutil import parser6namespaces = {7    'wml1.1':'{http://www.cuahsi.org/waterML/1.1/}',8    'wml1.0':'{http://www.cuahsi.org/waterML/1.0/}',9    'xsi':'{http://www.w3.org/2001/XMLSchema-instance',10    'xsd':'{http://www.w3.org/2001/XMLSchema'11}12def ns(namespace):13    return namespaces.get(namespace)14class XMLParser(object):15    """16        Convienence class; provides some useful shortcut methods to make retrieving xml elements from etree17        a little easier.18    """19    def __init__(self,xml_root,namespace):20        try:21            self._root = etree.parse(xml_root)22        except:23            self._root = xml_root24        if not namespace in namespaces:25            raise ValueError('Unsupported namespace passed in to parser!')26        self._ns = namespace27    def _find(self,tofind):28        try:29            return self._root.find(namespaces.get(self._ns) + tofind)30        except:31            return None32    def _findall(self,tofind):33        try:34            return self._root.findall(namespaces.get(self._ns) + tofind)35        except:36            return None37class SitesResponse(XMLParser):38    """39        Parses the response from a 'GetSites' request40        Parameters41        ===========42        :xmlio - A file-like object that holds the xml response from the request.43        Return 44        =======45        An object constructed from a dictionary parse of the response. The object has get access and can iterate46        over the sites returned.47    """48    def __init__(self,xml,version='wml1.1'):49        super(SitesResponse,self).__init__(xml,version)50        self.parse_sites_response()51    def __iter__(self):52        for s in self.sites:53            yield s54    def __getitem__(self,key):55        if isinstance(key,int) and key < len(self.sites):56            return self.sites[key]57        if isinstance(key,str):58            site = [site for site in self.sites for code in site.site_info.site_codes if code == key]59            if len(site) > 0:60                return site[0]61        raise KeyError('Unknown key ' + str(key))62    def parse_sites_response(self,xml=None):63        """64        """65        if xml is not None:66            try:67                self._root = etree.parse(xml)68            except:69                self._root = xml70        # try:71        self.query_info = QueryInfo(self._find('queryInfo'), self._ns)72        self.sites = [Site(site, self._ns) for site in self._findall('site')]73        # except:74        #   raise ValueError('Cannot parse sitesResponse element correctly')75    """Accesability properties/methods"""76    @property77    def site_codes(self):78        return [site.site_info.site_codes for site in self.sites]79    @property80    def site_names(self):81        return [site.site_info.site_name for site in self.sites]82class QueryInfo(XMLParser):83    """84    """85    def __init__(self,xml_root,version='wml1.1'):86        super(QueryInfo, self).__init__(xml_root,version)87        self.parse_query_info()88    def parse_query_info(self, xml=None):89        if xml is not None:90            try:91                self._root = etree.parse(xml)92            except:93                self._root = xml94        # try:95            # create queryinfo object from dict96        xml_dict = _xml_to_dict(self._root)97        self.creation_time = parser.parse(xml_dict.get('creation_time')) if xml_dict.get('creation_time') is not None else None98        self.notes = [testXMLValue(note) for note in self._findall('note')]99        self.criteria = Criteria(self._find('criteria'), self._ns)100        # except:101        #   raise ValueError('Unable to parse queryInfo element correctly')102class Criteria(XMLParser):103    """104    """105    def __init__(self,xml_root,version='wml1.1'):106        super(Criteria, self).__init__(xml_root,version)107        self.parse_criteria()108    def parse_criteria(self, xml=None):109        if xml is not None:110            try:111                self._root = etree.parse(xml)112            except:113                self._root = xml114        # try:115        xml_dict = _xml_to_dict(self._root,depth=4)116        self.method_called = self._root.attrib.get('MethodCalled')117        self.location_param = xml_dict.get('location_param')118        self.variable_param = xml_dict.get('variable_param')119        try:120            self.begin_date_time = parser.parse(xml_dict['begin_date_time'])121        except:122            self.begin_date_time = None123        try:124            self.end_date_time = parser.parse(xml_dict['end_date_time'])125        except:126            self.end_date_time = None127        self.parameters = [(param.attrib.get('name'),param.attrib.get('value')) for param in self._findall('parameter')]128        # except:129        #   raise ValueError('Unable to parse xml for criteria element')130class Site(XMLParser):131    def __init__(self, xml, version='wml1.1'):132        super(Site,self).__init__(xml,version)133        self.parse_site()134    def __iter__(self):135        for c in self.series_catalogs:136            yield c137    def __getitem__(self,key):138        if isinstance(key,int) and key < len(self.series_catalogs):139            return self.series_catalogs[key]140        if isinstance(key,str):141            var = [series.variable for catalog in self.series_catalogs for series in catalog if series.code == key]142            if len(var) > 0:143                return var[0]144        raise KeyError('Unknown key ' + str(key))145    """Accessor propeties/methods"""146    @property147    def name(self):148        return self.site_info.site_name149    @property150    def codes(self):151        return self.site_info.site_codes152    @property153    def variable_names(self):154        return list(set([series.variable.variable_name for catalog in self.series_catalogs for series in catalog]))155    @property156    def variable_codes(self):157        return list(set([series.variable.variable_code for catalog in self.series_catalogs for series in catalog]))158    @property159    def geo_coords(self):160        return self.site_info.location.geo_coords161    @property162    def latitudes(self):163        return [g[1] for g in self.site_info.location.geo_coords]164    @property165    def longitudes(self):166        return [g[0] for g in self.site_info.location.geo_coords]167    def parse_site(self,xml=None):168        if xml is not None:169            try:170                self._root = etree.parse(xml)171            except:172                self._root = xml173        # try:174        self.site_info = SiteInfo(self._find('siteInfo'), self._ns)175        self.series_catalogs = [SeriesCatalog(elm, self._ns) for elm in self._findall('seriesCatalog')]176            # self.extension = Extension(self._find('extension'), self._ns)177        # except:178        #   raise ValueError('Unable to parse site element correctly')179class SiteInfo(XMLParser):180    def __init__(self,xml,version='wml1.1'):181        super(SiteInfo,self).__init__(xml,version)182        self.parse_siteinfo()183    def parse_siteinfo(self,xml=None):184        if xml is not None:185            try:186                self._root = etree.parse(xml)187            except:188                self._root = xml189        # try:190        xml_dict = _xml_to_dict(self._root)191        self.site_name = xml_dict.get('site_name')192        self.site_codes = [testXMLValue(code) for code in self._findall('siteCode')]193        self.elevation = xml_dict.get('elevation_m')194        self.vertical_datum = xml_dict.get('vertical_datum')195        self.site_types = [testXMLValue(typ) for typ in self._findall('siteType')]196        self.site_properties = dict([(prop.attrib.get('name'),testXMLValue(prop)) for prop in self._findall('siteProperty')])197        self.altname = xml_dict.get('altname')198        self.notes = [testXMLValue(note) for note in self._findall('note')]199        # sub-objects200        tzi = self._find('timeZoneInfo')201        if tzi is not None:202            self.time_zone_info = TimeZoneInfo(tzi, self._ns)203        self.location = Location(self._find('geoLocation'), self._ns)204        # except:205        #   raise ValueError('Unable to parse siteInfo element')206class Location(XMLParser):207    def __init__(self,xml,version='wml1.1'):208        super(Location,self).__init__(xml,version)209        self.parse_location()210    def parse_location(self,xml=None):211        if xml is not None:212            try:213                self._root = etree.parse(xml)214            except:215                self._root = xml216        # try:217        xml_dict = _xml_to_dict(self._root)218        geogs = self._findall('geogLocation')219        self.geo_coords = list()220        self.srs = list()221        for g in geogs:222            self.geo_coords.append((testXMLValue(g.find(ns(self._ns) + 'longitude')),testXMLValue(g.find(ns(self._ns) + 'latitude'))))223            self.srs.append(g.attrib.get('srs'))224        locsite = self._findall('localSiteXY')225        self.local_sites = list()226        self.notes = list()227        self.projections = list()228        for ls in locsite:229            z = testXMLValue(ls.find(ns(self._ns) + 'Z'))230            if z is not None:231                self.local_sites.append((testXMLValue(ls.find(ns(self._ns) + 'X')),testXMLValue(ls.find(ns(self._ns) + 'Y')),z))232            else:233                self.local_sites.append((testXMLValue(ls.find(ns(self._ns) + 'X')),testXMLValue(ls.find(ns(self._ns) + 'Y')),'0'))234            self.notes.append([testXMLValue(note) for note in ls.findall(ns(self._ns) + 'note')])235            self.projections.append(ls.attrib.get('projectionInformation'))236        # except:237        #   raise ValueError('Unable to parse geoLocation element')238class TimeZoneInfo(XMLParser):239    def __init__(self,xml,version='wml1.1'):240        super(TimeZoneInfo,self).__init__(xml,version)241        self.parse_timezoneinfo()242    def parse_timezoneinfo(self,xml=None):243        if xml is not None:244            try:245                self._root = etree.parse(xml)246            except:247                self._root = xml248        # try:249        xml_dict = _xml_to_dict(self._root)250        default = self._find('defaultTimeZone')251        if default is not None:252          self.zone_offset = default.attrib.get('zoneOffset')253          self.zone_abbreviation = default.attrib.get('zoneAbbreviation')254        daylight = self._find('daylightSavingsTimeZone')255        if daylight is not None:256          self.daylight_zone_offset = daylight.attrib.get('zoneOffset')257          self.daylight_zone_abbreviation = daylight.attrib.get('zoneAbbreviation')258        # except:259        #   raise ValueError('Unable to properly parset the timeZoneInfo element')260            261class SeriesCatalog(XMLParser):262    def __init__(self,xml,version='wml1.1'):263        super(SeriesCatalog,self).__init__(xml,version)264        self.parse_seriescatalog()265    def __iter__(self):266        for s in self.series:267            yield s268    def __getitem__(self,key):269        if isinstance(key,int) and key < len(self.series):270            return self.series[key]271        if isinstance(key,str):272            srs = [series for series in self.series if series.code == key]273            if len(srs) > 0:274                return srs[0]275        raise KeyError('Unknown key ' + str(key))276    def parse_seriescatalog(self,xml=None):277        if xml is not None:278            try:279                self._root = etree.parse(xml)280            except:281                self._root = xml282        # try:283        self.series = [Series(elm,self._ns) for elm in self._findall('series')]284        # except:285        #   raise ValueError('Unable to properly parse the seriesCatalog element')286class Series(XMLParser):287    def __init__(self,xml,version='wml1.1'):288        super(Series,self).__init__(xml,version)289        self.parse_series()290    """Accessor proeprties/methods"""291    @property292    def name(self):293        return self.variable.variable_name294    @property295    def code(self):296        return self.variable.variable_code297    def parse_series(self,xml=None):298        if xml is not None:299            try:300                self._root = etree.parse(xml)301            except:302                self._root = xml303        # try:304        xml_dict = _xml_to_dict(self._root,depth=3)305        self.value_count = xml_dict.get('value_count')306        self.value_type = xml_dict.get('value_type')307        self.general_category = xml_dict.get('general_category')308        self.sample_medium = xml_dict.get('sample_medium')309        self.data_type = xml_dict.get('data_type')310        # date-time311        self.begin_date_time = parser.parse(xml_dict.get('begin_date_time'))312        self.begin_date_time_utc = parser.parse(xml_dict.get('begin_date_time_utc')) if xml_dict.get('begin_date_time_utc') is not None else None313        self.end_date_time = parser.parse(xml_dict.get('end_date_time'))314        self.end_date_time_utc = parser.parse(xml_dict.get('end_date_time_utc')) if xml_dict.get('end_date_time_utc') is not None else None315        # method info316        self.method_description = xml_dict.get('method_description')317        self.method_code = xml_dict.get('method_code')318        self.method_link = xml_dict.get('method_link')319        method = self._find('method')320        if method is not None:321            self.method_id = method.attrib.get('methodID')322        else:323            self.method_id = None324        # source info325        self.organization = xml_dict.get('organization')326        self.source_description = xml_dict.get('source_description')327        self.citation = xml_dict.get('citation')328        source = self._find('source')329        if source is not None:330            self.source_id = source.attrib.get('sourceID')331        else:332            self.source_id = None333        # quality control info334        self.quality_control_level_code = xml_dict.get('quality_control_level_code')335        self.definition = xml_dict.get('definition')336        qa = self._find('qualityControlLevel')337        if qa is not None:338            self.quality_control_level_id = qa.attrib.get('qualityControlLevelID')339        else:340            self.quality_control_level_id = None341        # properties342        self.properties = dict([(prop.attrib.get('name'),testXMLValue(prop)) for prop in self._findall('seriesProperty')])343        # sub-objects344        self.variable = Variable(self._find('variable'),self._ns)345        # except:346        #   raise ValueError('Unable to correctly parse Series element')347class Variable(XMLParser):348    def __init__(self,xml,version='wml1.1'):349        super(Variable,self).__init__(xml,version)350        self.parse_variable()351    def parse_variable(self,xml=None):352        if xml is not None:353            try:354                self._root = etree.parse(xml)355            except:356                self._root = xml357        # try:358        xml_dict = _xml_to_dict(self._root)359        self.value_type = xml_dict.get('value_type')360        self.data_type = xml_dict.get('data_type')361        self.general_category = xml_dict.get('general_category')362        self.sample_medium = xml_dict.get('sample_medium')363        self.no_data_value = xml_dict.get('no_data_value')364        self.variable_name = xml_dict.get('variable_name')365        self.variable_code = xml_dict.get('variable_code')366        self.variable_description = xml_dict.get('variable_description')367        self.speciation = xml_dict.get('speciation')368        # notes and properties369        notes = [(note.attrib.get('title'),testXMLValue(note)) for note in self._findall('note')]370        none_notes = [note[1] for note in notes if note[0] is None]371        self.notes = dict([note for note in notes if note[0] is not None])372        if len(none_notes) > 0:373            self.notes['none'] = none_notes374        self.properties = dict([(prop.attrib.get('name'),testXMLValue(prop)) for prop in self._findall('variableProperty')])375        # related376        related = self._find('related')377        if related is not None:378            self.parent_codes = [dict([('network',code.attrib.get('network')),('vocabulary',code.attrib.get('vocabulary')),('default',code.attrib.get('default'))])379                             for code in related.findall(ns(self._ns) + 'parentCode')]380            self.related_codes = [dict([('network',d.get('network')),('vocabulary',d.get('vocabulary')),('default',d.get('default'))])381                             for code in related.findall(ns(self._ns) + 'relatedCode')]382        else:383            self.parent_codes = None384            self.related_codes = None385        # sub-objects386        if self._ns == 'wml1.0':387            unit = self._find('units')388            self.unit = Unit1_0(unit, self._ns) if unit is not None else None389            timesupport = self._find('timeSupport')390            self.time_support = TimeScale(timesupport, self._ns) if timesupport is not None else None391        else:392            unit = self._find('unit')393            self.unit = Unit(unit, self._ns) if unit is not None else None394            timescale = self._find('timeScale')395            self.time_scale = TimeScale(timescale, self._ns) if timescale is not None else None396        categories = self._find('categories')397        if categories is not None:398            self.categories = [Category(cat,self._ns) for cat in categories.findall(ns(self._ns) + 'category')]399        else:400            self.categories = None401        # except:402        #   raise ValueError('Unable to correctly parse variable element')403class TimeScale(XMLParser):404    def __init__(self,xml,version='wml1.1'):405        super(TimeScale,self).__init__(xml,version)406        self.parse_timescale()407    def parse_timescale(self):408        try:409            xml_dict = _xml_to_dict(self._root)410            self.time_spacing = xml_dict.get('time_spacing')411            self.time_support = xml_dict.get('time_support')412            self.time_interval = xml_dict.get('time_interval')413            unit = self._find('unit')414            self.unit = Unit(unit, self._ns) if unit is not None else None415        except:416            raise417class Unit(XMLParser):418    def __init__(self,xml,version='wml1.1'):419        super(Unit,self).__init__(xml,version)420        self.parse_unit()421    def parse_unit(self):422        try:423            xml_dict = _xml_to_dict(self._root)424            self.name = xml_dict.get('unit_name')425            self.unit_type = xml_dict.get('unit_type')426            self.description = xml_dict.get('unit_description')427            self.abbreviation = xml_dict.get('unit_abbreviation')428            self.code = xml_dict.get('unit_code')429            self.id = self._root.attrib.get('UnitID')430        except:431            raise432class Unit1_0(XMLParser):433    def __init__(self,xml,version='wml1.0'):434        super(Unit1_0,self).__init__(xml,version)435        self.parse_unit()436    def parse_unit(self):437        try:438            self.name = testXMLValue(self._root)439            self.code = self._root.attrib.get('unitsCode')440            self.abbreviation = self._root.attrib.get('unitsAbbreviation')441            self.type = self._root.attrib.get('unitsType')442            self.id = self._root.attrib.get('unitID')443        except:444            raise445class Category(XMLParser):446    def __init__(self,xml,version='wml1.1'):447        super(Category,self).__init__(xml,version)448        self.parse_category()449    def parse_category(self):450        try:451            xml_dict = _xml_to_dict(self._root)452            self.data_value = xml_dict.get('data_value')453            self.description = xml_dict.get('description')454            self.id = self._root.attrib.get('categoryID')455        except:456            raise457class TimeSeriesResponse(XMLParser):458    """459        Parses the response from a 'GetValues' request460        Parameters461        ===========462        :xmlio - A file-like object that holds the xml response from the request.463        Return 464        =======465        An object constructed from a dictionary parse of the response. The object has get access and can466        also iterate over each timeSeries element returned.467    """468    def __init__(self,xml,version='wml1.1'):469        super(TimeSeriesResponse,self).__init__(xml,version)470        self.parse_timeseriesresponse()471    """Accessor properties/methods"""472    @property473    def series_names(self):474        return [series.name for series in self.time_series]475    @property476    def variable_names(self):477        return list(set([series.variable.variable_name for series in self.time_series]))478    @property479    def variable_codes(self):480        return list(set([s.variable.variable_code for s in self.time_series]))481    def get_series_by_variable(self,var_name=None,var_code=None):482        if var_code is not None:483            return [s for s in self.time_series if s.variable.variable_code == var_code]484        elif var_name is not None:485            return [series for series in self.time_series if series.variable.variable_name == var_name]486        return None487    def parse_timeseriesresponse(self):488        try:489            qi = self._find('queryInfo')490            self.query_info = QueryInfo(qi,self._ns)491            self.time_series = [TimeSeries(series,self._ns) for series in self._findall('timeSeries')]492        except:493            raise494class TimeSeries(XMLParser):495    def __init__(self,xml,version='wml1.1'):496        super(TimeSeries,self).__init__(xml,version)497        self.parse_timeseries()498    def parse_timeseries(self):499        try:500            self.variable = Variable(self._find('variable'), self._ns)501            self.values = [Values(val,self._ns) for val in self._findall('values')]502            self.source_info = SiteInfo(self._find('sourceInfo'), self._ns)503            self.name = self._root.attrib.get('name')504        except:505            raise506class Values(XMLParser):507    def __init__(self,xml,version='wml1.1'):508        super(Values,self).__init__(xml,version)509        self.parse_values()510    def __iter__(self):511        for v in self.values:512            yield v513    """Accessor properties/methods"""514    def get_date_values(self,method_id=None,source_id=None,sample_id=None,quality_level=None,utc=False):515        varl = [v for v in self.values]516        if method_id is not None:517            varl = [v for v in varl if v.method_id == method_id]518        if source_id is not None:519            varl = [v for v in varl if v.source_id == source_id]520        if sample_id is not None:521            varl = [v for v in varl if v.sample_id == sample_id]522        if quality_level is not None:523            varl = [v for v in varl if v.quality_control_level == quality_level]524        if not utc:525            return [(v.date_time,v.value) for v in varl]526        else:527            return [(v.date_time_utc,v.value) for v in varl]528    def parse_values(self):529        xml_dict = _xml_to_dict(self._root)530        # method info531        self.methods = [Method(method,self._ns) for method in self._findall('method')]532        # source info533        self.sources = [Source(source,self._ns) for source in self._findall('source')]534        # quality control info535        self.qualit_control_levels = [QualityControlLevel(qal, self._ns) for qal in self._findall('qualityControlLevel')]536        # offset info537        self.offsets = [Offset(os,self._ns) for os in self._findall('offset')]538        # sample info539        self.samples = [Sample(sample,self._ns) for sample in self._findall('sample')]540        # censor codes541        self.censor_codes = [CensorCode(code, self._ns) for code in self._findall('censorCode')]542        # unit543        if self._ns == 'wml1.0':544            self.unit_abbreviation = self._root.attrib.get('unitsAbbreviation')545            self.unit_code = self._root.attrib.get('unitsCode')546            self.count = self._root.attrib.get('count')547        else:548            unit = self._find('unit')549            self.unit = Unit(unit, self._ns) if unit is not None else None550        # values551        self.values = [Value(val, self._ns) for val in self._findall('value')]552class Value(XMLParser):553    def __init__(self,xml,version='wml1.1'):554        super(Value,self).__init__(xml,version)555        self.parse_value()556    def parse_value(self):557        try:558            self.value = testXMLValue(self._root)559            d = self._root.attrib560            self.qualifiers = d.get('qualifiers')561            self.censor_code = d.get('censorCode')562            self.date_time = parser.parse(d.get('dateTime')) if d.get('dateTime') is not None else None563            self.time_offset = d.get('timeOffset')564            self.date_time_utc = parser.parse(d.get('dateTimeUTC')) if d.get('dateTimeUTC') is not None else None565            self.method_id = d.get('methodID')566            self.source_id = d.get('sourceID')567            self.accuracy_std_dev = d.get('accuracyStdDev')568            self.sample_id = d.get('sampleID')569            self.method_code = d.get('methodCode')570            self.source_code = d.get('sourceCode')571            self.lab_sample_code = d.get('lab_sample_code')572            self.offset_value = d.get('offsetValue')573            self.offset_type_id = d.get('offsetTypeID')574            self.offset_type_code = d.get('offsetTypeCode')575            self.coded_vocabulary = d.get('codedVocabulary')576            self.coded_vocabulary_term = d.get('codedVocabularyTerm')577            self.quality_control_level = d.get('qualityControlLevel')578            self.metadata_time = d.get('metadataTime')579            self.oid = d.get('oid')580        except:581            raise582class Sample(XMLParser):583    def __init__(self,xml,version='wml1.1'):584        super(Sample,self).__init__(xml,version)585        self.parse_sample()586    def parse_sample(self):587        try:588            xml_dict = _xml_to_dict(self._root)589            self.code = xml_dict.get('lab_sample_code')590            self.type = xml_dict.get('sample_type')591            lm = self._find('labMethod')592            self.method = LabMethod(lm, self._ns) if lm is not None else None593        except:594            raise595class LabMethod(XMLParser):596    def __init__(self,xml,version='wml1.1'):597        super(LabMethod,self).__init__(xml,version)598        self.parse_labmethod()599    def parse_labmethod(self):600        try:601            xml_dict = _xml_to_dict(self._root)602            self.code = xml_dict.get('lab_code')603            self.name = xml_dict.get('lab_name')604            self.organization = xml_dict.get('lab_organization')605            self.method_name = xml_dict.get('lab_method_name')606            self.method_description = xml_dict.get('lab_method_description')607            self.method_link = xml_dict.get('lab_method_link')608            # sub-objects609            source = self._find('labSourceDetails')610            self.source_details = Source(source,self._ns) if source is not None else None611        except:612            raise613class Source(XMLParser):614    def __init__(self,xml,version='wml1.1'):615        super(Source,self).__init__(xml,version)616        self.parse_source()617    def __str__(self):618        return str(self.__dict__)619    def get_contact(self,name):620        ci = [ci for ci in self.contact_info if ci.name == name]621        if len(ci) < 0:622            return ci[0]623        return None624    def parse_source(self):625        try:626            xml_dict = _xml_to_dict(self._root)627            self.code = xml_dict.get('source_code')628            self.organization = xml_dict.get('organization')629            self.description = xml_dict.get('source_description')630            self.links = [testXMLValue(link) for link in self._findall('sourceLink')]631            self.citation = xml_dict.get('citation')632            # metadata633            self.topic_category = xml_dict.get('topic_category')634            self.title = xml_dict.get('title')635            self.abstract = xml_dict.get('abstract')636            self.profile_version = xml_dict.get('profile_version')637            self.metadata_link = xml_dict.get('metadata_link')638            # contact info639            self.contact_info = [ContactInformation(ci,self._ns) for ci in self._findall('contactInformation')]640        except:641            raise642class ContactInformation(XMLParser):643    def __init__(self,xml,version='wml1.1'):644        super(ContactInformation,self).__init__(xml,version)645        self.parse_contactinformation()646    def parse_contactinformation(self):647        try:648            xml_dict = _xml_to_dict(self._root)649            self.name = xml_dict.get('contact_name')650            self.type = xml_dict.get('type_of_contact')651            self.email = [testXMLValue(email) for email in self._findall('email')]652            self.phone = [testXMLValue(phone) for phone in self._findall('phone')]653            self.address = [testXMLValue(address) for address in self._findall('address')]654        except:655            raise656class Offset(XMLParser):657    def __init__(self,xml,version='wml1.1'):658        super(Offset,self).__init__(xml,version)659        self.parse_offset()660    def parse_offset(self):661        try:662            xml_dict = _xml_to_dict(self._root)663            self.type_code = xml_dict.get('offset_type_code')664            self.value = xml_dict.get('offset_value')665            self.description = xml_dict.get('offset_description')666            self.is_vertical = xml_dict.get('offset_is_vertical')667            self.azimuth_degrees = xml_dict.get('offset_azimuth_degrees')668            unit = self._root.find('unit')669            if self._ns == 'wml1.0':670                self.unit = Unit1_0(unit, self._ns) if unit is not None else None671            else:672                self.unit = Unit(unit,self._ns) if unit is not None else None673        except:674            raise675class Method(XMLParser):676    def __init__(self,xml,version='wml1.1'):677        super(Method,self).__init__(xml,version)678        self.parse_method()679    def parse_method(self):680        try:681            xml_dict = _xml_to_dict(self._root)682            self.code = xml_dict.get('method_code')683            self.description = xml_dict.get('method_description')684            self.link = xml_dict.get('method_link')685            self.id = self._root.attrib.get('methodID')686        except:687            raise688class QualityControlLevel(XMLParser):689    def __init__(self,xml,version='wml1.1'):690        super(QualityControlLevel,self).__init__(xml,version)691        self.parse_qcl()692    def parse_qcl(self):693        try:694            xml_dict = _xml_to_dict(self._root)695            self.code = xml_dict.get('quality_control_level_code')696            self.definition = xml_dict.get('definition')697            self.explanation = xml_dict.get('explanation')698            self.id = self._root.attrib.get('qualityControlLevelID')699        except:700            raise701class CensorCode(XMLParser):702    def __init__(self,xml,version='wml1.1'):703        super(CensorCode,self).__init__(xml,version)704        self.parse_censorcode()705    def parse_censorcode(self):706        try:707            xml_dict = _xml_to_dict(self._root)708            self.code = xml_dict.get('censor_code')709            self.description = xml_dict.get('censor_code_description')710            self.id = self._root.attrib.get('censorCodeID')711        except:712            raise713class VariablesResponse(XMLParser):714    """715        Parses the response from a 'GetVariableInfo' request716        Parameters717        ===========718        :xmlio - A file-like object that holds the xml response from the request.719        Return720        =======721        An object constructed from a dictionary parse of the response. The object has get access to its variables and722        can also be used as an iterator.723    """724    def __init__(self,xml,version='wml1.1'):725        super(VariablesResponse,self).__init__(xml,version)726        self.parse_variablesresponse()727    def __iter__(self):728        for v in self.variables:729            yield v730    def __getitem__(self,key):731        if isinstance(key,int) and key < len(self.variables):732            return self.variables[key]733        if isinstance(key,str):734            v = [var for var in self.variables if var.variable_code == key]735            if len(v) > 0:736                return v[0]737            v = [var for var in self.variables if var.variable_name == key]738            if len(v) > 0:739                return v[0]740        raise KeyError('Unknown key ' + str(key))741    """Accessor properties/methods"""742    @property743    def variable_names(self):744        return list(set([var.variable_name for var in self.variables]))745    @property746    def variable_codes(self):747        return  [var.variable_code for var in self.variables]748    def parse_variablesresponse(self):749        try:750            qi = self._find('queryInfo')751            self.query_info = QueryInfo(qi, self._ns) if qi is not None else None752            varis = self._find('variables')753            self.variables = [Variable(var,self._ns) for var in varis.findall(ns(self._ns) + 'variable')]754        except:...setup.py
Source:setup.py  
1#!/usr/bin/env python2# This file is part of ranger, the console file manager.3# License: GNU GPL version 3, see the file "AUTHORS" for details.4import distutils.core5import os.path6import ranger7def _findall(directory):8    return [os.path.join(directory, f) for f in os.listdir(directory) \9            if os.path.isfile(os.path.join(directory, f))]10if __name__ == '__main__':11    distutils.core.setup(12        name='ranger',13        description='Vim-like file manager',14        long_description=ranger.__doc__,15        version=ranger.__version__,16        author=ranger.__author__,17        author_email=ranger.__email__,18        license=ranger.__license__,19        url='http://ranger.nongnu.org',20        scripts=['scripts/ranger', 'scripts/rifle'],21        data_files=[22            ('share/applications',23                ['doc/ranger.desktop']),24            ('share/man/man1',25                ['doc/ranger.1',26                 'doc/rifle.1']),27            ('share/doc/ranger',28                ['README.md',29                 'CHANGELOG.md',30                 'HACKING.md',31                 'doc/colorschemes.txt']),32            ('share/doc/ranger/config/colorschemes',33                _findall('doc/config/colorschemes')),34            ('share/doc/ranger/config', _findall('doc/config')),35            ('share/doc/ranger/tools', _findall('doc/tools')),36            ('share/doc/ranger/examples', _findall('examples')),37        ],38        package_data={'ranger': ['data/*', 'config/rc.conf',39            'config/rifle.conf']},40        packages=('ranger',41                  'ranger.api',42                  'ranger.colorschemes',43                  'ranger.container',44                  'ranger.core',45                  'ranger.config',46                  'ranger.ext',47                  'ranger.gui',48                  'ranger.gui.widgets',...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
