source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/util/oasisgui/XDRpy/XDR.py @ 4775

Last change on this file since 4775 was 4775, checked in by aclsce, 5 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 52.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3 # __   _______  _____             
4 # \ \ / /  __ \|  __ \             
5 #  \ V /| |  | | |__) |_ __  _   _
6 #   > < | |  | |  _  /| '_ \| | | |
7 #  / . \| |__| | | \ \| |_) | |_| |
8 # /_/ \_\_____/|_|  \_\ .__/ \__, |
9 #                     | |     __/ |
10 #                     |_|    |___/
11
12"""
13
14XDR.py
15------
16
17Created  by A. Dauptain and G Frichet
18
19Main generic tools for C3Sm interface
20Requires version 2.6.6 or later of python 2
21Does not run with python 3
22
23
24
25"""
26import sys
27if ((sys.hexversion < 0x020606F0) or
28    (sys.hexversion > 0x030000A0)):
29    raise Exception(
30            "Must be run with python version at least 2.6.6, and not python 3\n"
31            "Your version is %i.%i.%i" % sys.version_info[:3])
32
33from xml.dom.minidom import *
34import xml.parsers.expat
35import time, os, subprocess, re, string,shutil
36import filecmp
37import fileinput
38import imp
39import codecs
40from itertools import izip
41import shlex
42
43import glob
44
45
46# Warnig cannot be importedblike this :
47#if we use xdrpy on distant locations, SAV will be missing
48#import SAV
49
50
51
52
53"""
54This library intends to provide methods to access and modify XML datasets read and written
55by C3Sm.
56Moreover, this library provides methods to deal with ascii files that might be read and written by external programs.
57
58There are two parts in this library :
59The first one is composed of high-level procedures.
60The second one is a set of classes used by the high-level procedures.
61Normal developers does not have to use them, even if they can !"""
62
63 # _    _ _       _       _                _
64 #| |  | (_)     | |     | |              | |
65 #| |__| |_  __ _| |__   | | _____   _____| |
66 #|  __  | |/ _` | '_ \  | |/ _ \ \ / / _ \ |
67 #| |  | | | (_| | | | | | |  __/\ V /  __/ |
68 #|_|  |_|_|\__, |_| |_| |_|\___| \_/ \___|_|
69 #           __/ |                           
70 #          |___/                           
71
72def init():
73    """
74    This procedure initializes the XDR environment.
75    It must be called at the beginning of every script using XDR.
76   
77    ==== Dev =====
78    This procedures creates an interface "dsin" for reading XML file "dataset.xml" produced by C3Sm
79    It creates also a copy of this dataset "dsout", modifiable, to be read by C3Sm, "out_dataset.xml"
80    It also stores useful paths (current directory at launch of the script (not to lose C3Sm) and script directory)
81    """   
82   
83    global dsin
84    global dsout
85    global startingDir
86    global scriptDir
87    global verbose
88    global OrigAppName
89    global projectName
90   
91    global timestamp
92    global COMMON_DIRECTORY,PREFIX,DIGIT_NUMBER
93
94   
95    verbose = 0
96    startingDir=os.getcwd()
97    scriptDir=os.path.dirname(os.path.abspath(sys.modules['__main__'].__file__))
98
99    dsin=Dataset("dataset.xml")
100    dsout=Dataset("dataset.xml")
101    os.remove("dataset.xml")
102   
103    OrigAppName = dsout.getValue("name","solver","meta")
104    projectName = dsout.getValue("name","project","meta")
105   
106   
107   
108    print "Local  use of XDRpy for project ",projectName, "(",OrigAppName,")"
109   
110   
111    print  dsout.getValue("pluginsPath","engine","meta")
112    #
113   
114    PREFIX = "RUN_"
115    DIGIT_NUMBER = 3
116    COMMON_DIRECTORY = "COMMON"
117   
118    if OrigAppName == "none" :
119        print "Warning : XDRpy unable to find the origin application"
120    else :
121        print "XDRpy running for application : ",OrigAppName
122        COMMON_DIRECTORY = os.path.join(COMMON_DIRECTORY,OrigAppName.upper())
123   
124   
125   
126   
127    timestamp = time.time()
128   
129    return dsin,dsout
130
131def finish(a=0):
132    """
133    This procedure closes the XDR environment.
134    It must be called at the end of every script using XDR.
135   
136    ==== Dev ====
137    This procedure saves the output XML file and changes the directory to the initial one
138    """
139
140    oldDir = os.getcwd()
141    os.chdir(startingDir)
142    if a != 0 :
143        a.save2file("out_dataset.xml")
144    else :
145        try:
146            dsout.save2file("out_dataset.xml")
147           
148        except NameError:
149            pass
150
151def progress(percent,message):
152    """ This function lets c3sm know progresse of the current script
153    percent is the percentage of work done (0 < percent < 100)
154    message is a little status written by the progressbar, it shouldn't be too long
155    """
156    global timestamp
157   
158    time.sleep(0.1)
159    newtime = time.time()
160
161    print "%"+str(int(percent))+"%"+str(message)
162    print '{0:2f}'.format(newtime-timestamp-0.1)+"s \n"+ str(int(percent))+"% "+str(message) 
163    sys.stdout.flush()
164    timestamp=newtime
165   
166   
167def getDsin():
168    """ This procedure returns the Dataset object representing the input xml file """
169    try:
170        return dsin
171    except NameError:
172        error("XDRError : XDR library must be initialized")
173       
174       
175def getDsout():
176    """ This procedure returns the Dataset object representing the current dataset """
177    try:
178        return dsout
179    except NameError:
180        error("XDRError : XDR library must be initialized")
181   
182
183def tryGetValue(default, key, *path):
184    """
185    Search for the node "nodeName" with elements of "path" in its path and return its value
186    If node doesn't exist, catch XDRnoNodeException end return the default value
187   
188    It would be cleaner to use "path" as a list, instead of "*path", but this would change all the geValue calls :(
189        To be evaluated later
190    """
191    return dsout.tryGetValue(default, key, *path)
192
193
194def getValue(key,*path):
195    """
196    This procedure returns the value of a specified tag in the dataset.
197    If more than one node have the same name, one or more parts of the path have to be specified.
198    Ex :
199    getValue("myParam")
200    or
201    getValue("myParam","parent","parent of parent")
202   
203    It would be cleaner to use "path" as a list, instead of "*path", but this would change all the geValue calls :(
204        To be evaluated later
205    """
206    return dsout.getValue(key,*path)
207   
208
209def getListValue(key,*path):
210    """
211    This procedure gets the asked value from the dataset and returns it as a list
212    """
213    return dsout.getListValue(key,*path)
214
215
216def getIntegerValue(key,*path):
217    """
218    This procedure returns an integer corresponding to the value of a specified tag in the dataset.
219    If more than one node have the same name, one or more parts of the path have to be specified.
220    """
221    return int(dsout.getValue(key,*path))
222
223
224def getFloatValue(key,*path):
225    """
226    This procedure returns a float corresponding to the value of a specified tag in the dataset.
227    If more than one node have the same name, one or more parts of the path have to be specified.
228    """
229    return float(dsout.getValue(key,*path))
230
231
232def getChildrenName(nodeName,*path):
233    """
234    This procedure returns a list of the name of all the children of the node named "nodeName".
235    If more than one node has the same name, parts of its path can be specified as for the getValue method
236    """
237    return dsout.getChildrenName(nodeName,*path)
238
239
240def setValue(value,nodeName,*path):
241    """
242    This procedure modifies the node specify and set its value to "value"
243    If more than one node has the same name, parts of its path can be specified as for the getValue method
244    """
245    dsout.setValue(value,nodeName,*path)
246   
247
248def nodeExists(nodeName,*path):
249    """
250    This procedure checks if the node exists or not. It returns 1 if it exists, 0 if not
251    """
252    return dsout.nodeExists(nodeName,*path)
253   
254
255
256 #
257 # ______                     _       
258 #|  ____|                   | |     
259 #| |__  __  _____  ___ _   _| |_ ___
260 #|  __| \ \/ / _ \/ __| | | | __/ _ \
261 #| |____ >  <  __/ (__| |_| | ||  __/
262 #|______/_/\_\___|\___|\__,_|\__\___|
263 #                                   
264                                     
265def execute(command, always_print_err=False, silent=True):
266    """
267    This procedure searches for the specified executable in the script directory, if not, it tries to execute the command itself.
268    The command is then executed and its output is printed in standard output
269    """
270    ####### Need some work to handle long run and reading of the output on the fly !
271    if (os.path.exists(os.path.join(scriptDir,command))):
272        command=os.path.join(scriptDir,command)
273    print "command "+ command
274    command=shlex.split(command)
275    if silent == False :
276        print "Executing " + repr(command) + ' in ' + repr(os.getcwd()) + ':\n' + 50*'-' + '\n'
277    read_from = None
278    if "<" in command :
279        read_from = command[-1]
280        command = command[:-2]
281    p=subprocess.Popen(command,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
282    if read_from:
283        p.stdin.write(open(read_from, "r").read())
284
285    stdout_data = []
286    if silent == False :
287        print "\nXDRExecute =============StdOut=================\n"
288    while True:
289        line = p.stdout.readline()
290        if not line:
291            break
292        if silent == False :
293            print 'XDRExecute ' + line.rstrip()
294        sys.stdout.flush()
295        stdout_data.append(line)
296    returncode = p.wait()
297    stderr_data = p.stderr.read()
298   
299    if ( always_print_err and not returncode ):
300        if silent == False :
301            print "\nXDRExecute =============StdErr=================\n"
302            print 'XDRExecute ' + "\nXDRExecute ".join(stderr_data.split('\n'))
303    # if traite "None" "0" False" "" Comme des retours negatif
304    if returncode:
305        error("Problem while running command :"+" ".join(command)+"\n=============StdErr=================\n"+stderr_data)
306    return "".join(stdout_data)
307
308
309
310 #
311 #  _____     _     
312 # / ____|   | |   
313 #| (___  ___| |__ 
314 # \___ \/ __| '_ \
315 # ____) \__ \ | | |
316 #|_____/|___/_| |_|
317 #                 
318                           
319def ssh_host(host, login):
320    """reconstruct full host description"""   
321    full_host = host
322    if host == None or host == "":
323        error("SSH host unspecified")
324   
325    if login != None and login != "":
326        full_host = login + '@' + host
327
328    return full_host
329
330def ssh(host, login, command, options=""):
331    """ Executes a command through SSH """
332    # TODO: check that we are on a platform were ssh actually exists
333    full_host = ssh_host(host, login)
334
335    output= execute("""ssh """ + options + """ """ + full_host + """ '"""+command+"""'""")
336    return output
337
338def ssh_prepare_directory(host, login, distant_directory):
339    """ Prepare (creates) a directory on a distant server """
340    # TODO: check that we are on a platform where ssh actually exists
341
342    if len(distant_directory) == 0:
343        error("Please specify a distant directory, for example : /home/toto/")
344
345    if distant_directory[0] != '/' and distant_directory[0] != '~':
346        error("Relative path given. Please specify an absolute path")
347
348    print "Making sure distant directory is ready..."
349    command = """mkdir -p """ + distant_directory
350    ssh(host, login, command)
351
352def ssh_send(host, login, distant_directory, local_directories_list, options=""):
353    """ Uploads files to a server using ssh.
354        This creates a tar archive, and pipes it through ssh to a 'tar xf' on the distant side.
355        In short, the command that we run is:
356        tar cf - directory1 directory2 | ssh distant_server "tar xf - -C distant_directory"
357        (with some additional safety)
358    """
359    # TODO: check that we are on a platform where tar, scp, ssh actually exist
360
361    # TODO: Check that local_directories_list is actually a list.
362    # People will try with string, and it does bad things with strings.
363
364    full_host = ssh_host(host, login)
365
366    if (len(local_directories_list) == 0):
367        print "No directories to be sent"
368        return
369
370
371    print "Sending and extracting archive..."
372   
373    # Decomposition
374    # Bash : passage en bash
375    # -c  :(...)
376    # tar cvf : compresse
377    # local directoryes_list (liste de tous les rep a envoyer)
378    # - : vers le pipe
379    # | : pipe
380    # ssh mylogin@host -
381    # \:(...)
382    # tarc xv : decompresse
383    # - depuis le pipe
384    # -C:(...)
385    # distant directory : Dans la directory distante
386    # \ :(...)
387   
388    command = """bash -c "tar cvf - """ + (" ".join(local_directories_list)) + """ | ssh """ + full_host + """ \\\"tar xf - -C """ + distant_directory + """\\\" " """
389    #print "ssh_send command ",command
390    execute(command,always_print_err=True)
391
392def ssh_retrieve(host, login, distant_directory, directory, options=""):
393    """ Transfers files from a server using ssh.
394        This is the opposite of ssh_send, except it operates on a single directory.
395    """
396    # TODO: check that we are on a platform where scp actually exists
397    full_host = ssh_host(host, login)
398   
399   
400    # M RIVIERE Solution -Deprecated-  ( Il y a pb non resolu dedans)
401   
402    # Decomposition
403    # Bash : passage en bash
404    # -c  : interprete la chaine de caractÚres suivante
405    # ssh mylogin@host -
406    # \:(...)
407    # tar cvf : compresse
408    # - : vers le pipe
409    # -C:(...)
410    # distant directory
411    # local directory
412    # \ :(...)
413    # | : pipe
414    # tarc xvf : decompresse
415    # - depuis le pipe
416    #command = """bash -c "ssh """ + full_host + """ \' tar cvf - -C """ + distant_directory + """ """ + directory + """\\\" | tar xvf -" """
417   
418    # G DEJEAN Sokution
419    # Decomposition
420    # Bash : passage en bash
421    # -c  : interprete la chaine de caractÚres suivante
422    # ssh mylogin@host
423    # '
424    # cd distant directory:
425    # tar cvf : compresse
426    # - : vers le pipe
427    # . : le repretoire courant
428    # '
429    # | : pipe
430    # tar -x vf : decompresse
431    # -C local directory : en renommant le repertoire
432    # -vf :
433    # - :depuis le pipe
434    command = """bash -c " ssh """ + full_host + """ 'cd """+ distant_directory + """;  tar cvf - .'| tar -x -C """ +directory+""" -vf - " """
435   
436    print "ssh_retrieve command ",command
437    execute(command,always_print_err=True)
438
439
440def ssh_cleanup_directory(host, login, distant_directory, directory):
441    """ Remove a directory on distant ssh server """
442    print "Cleaning up distant files..."
443    command = """rm -rf """ + distant_directory + """/""" + directory
444    ssh(host, login, command)
445
446def tar(file, filelist):
447    """ Create an archive from a list of files """
448    # TODO: Windows support ? Use pkgfile.py or something ?
449    execute("tar cvf " + file + " " + " ".join(filelist))
450
451
452
453def error(txt):
454    """
455    This procedure stops the script and make sure to say it to C3Sm
456    """
457    try :
458        dsout.setValue("0","scriptSuccess","meta")
459    except NameError:
460        pass
461    print "Error : "+txt
462    finish()
463    exit()
464   
465
466def verbose():
467    """ This procedure activates verbosing for the library"""
468    global verbose
469    verbose = 1
470    print "Verbose activated ... ("+str(verbose)+") "
471   
472   
473def getScriptDir():
474    """ This accessor returns the value of the script directory for the current solver"""
475    global scriptDir
476    return scriptDir
477
478def getCommonDir():
479    """ This accessor returns the value of the script directory for the current solver"""
480    global COMMON_DIRECTORY
481    return COMMON_DIRECTORY
482
483
484 #   
485 # _____        _                 _   
486 #|  __ \      | |               | | 
487 #| |  | | __ _| |_ __ _ ___  ___| |_
488 #| |  | |/ _` | __/ _` / __|/ _ \ __|
489 #| |__| | (_| | || (_| \__ \  __/ |_
490 #|_____/ \__,_|\__\__,_|___/\___|\__|
491 #                                   
492                                     
493class Dataset:
494    """ This class defines a reader for XML files written by C3Sm.
495    Specifying a XML file, the XDR interface stores the dataset and
496    implements several methods to access values and structures of the dataset"""
497   
498    def __init__(self,xmlfile):
499        """ XDR constructor : it needs a XML file from C3Sm """
500        self._xmlFile=xmlfile
501        try :
502            self._dom=parse(self._xmlFile)
503        except IOError:
504            error("XDRError : Problem with file system, check that permissions and free space are ok.\n"+xmlfile+" couldn't be read")
505        except xml.parsers.expat.ExpatError , err:
506            print err
507            XMLfile = open(self._xmlFile,"r").read().split("\n")
508            print "--> "+XMLfile[err.lineno+1]
509            print " "*(4+err.offset)+"^"
510           
511           
512            error("XDRError : Xml file from c3sm wasn't correct xml, please check that you have enough free space and you have the last version of C3Sm. Otherwise, please send dataset.xml from your project directory to C3Sm team")
513        self._root=self._dom.documentElement
514        self._currentNode=self._root
515        self._outputFile=""
516       
517    def __repr__(self):
518        return self._printNode() 
519   
520    def _printNode (self, sep=''):
521        """ This private method is a recursive method to describe the content of the dataset for debugging purpose"""
522        desc=""
523        node=self._currentNode
524        if node.nodeType == 1:
525            desc+= sep+node.nodeName+ ' >> '
526            for cle,valeur in node.attributes.items():
527                desc+= ' '+valeur+'   '
528            desc+="\n"
529        for child in node.childNodes:
530            self._currentNode=child
531            desc+=self._printNode(sep+'   ')
532            self._currentNode=node
533        return desc
534   
535    def _getTags(self,tagList):
536        node=self._currentNode
537        if node.nodeType == 1:
538            tagList.append(node.nodeName)
539        for child in node.childNodes:
540            self._currentNode=child
541            tagList = self._getTags(tagList)
542            self._currentNode=node
543        return tagList
544   
545    def _getNode(self,key,*path):       
546        try:
547            return self._searchNode(key,*path)
548        except XDRtooManyNodesException, e:
549            solverNode = self.getValue("callingAddress","action","meta")
550            solverNode= solverNode.split(".")[1]
551            return self._searchNode(key,solverNode,*path)
552
553    def _searchNode(self,key,*path):
554        """ This private method needs a key to search a node with name=key
555        If no node is found, an Exception is raisen
556        If one node is found, an Element is returned
557        If more than one node is, the most relevant one (according to path) is chosen and returned as an Element
558       
559        path is a list of keyword"""
560       
561        if not isinstance(key,basestring) :
562            raise XDRillFormed("XDRError : the type of key ", key , "is ", type(key), "instead of a basestring")     
563       
564        result=self._dom.getElementsByTagName(key)
565        if result.length==0:
566            raise XDRnoNodeException("XDRError : no node found with key "+str(key)+" and path containing "+str(path))
567        else :
568            resultToDel=[]
569            for i,elt in enumerate(result):
570                address=self._getAddress(elt)
571                for eltPath in path:
572                    if eltPath not in address:
573                        resultToDel.append(i)
574                        break
575            #Now, the result should be one item long, if not there is a problem
576            # Raising XDRnoNodeException or XDRtooManyNodesException
577            resultToDel.sort(reverse=True)
578            for i in resultToDel:
579                del result[i]
580           
581            if result.length == 1:
582                return result[0]
583            elif result.length == 0:
584                raise XDRnoNodeException("XDRError : no node found with key "+str(key)+" and path containing "+str(path))
585            else:
586
587                errMsg = "XDRError :"+str(result.length)+" nodes found with key '"+str(key)+"' and path "+str(path)+" :\n"
588                for elt in result:
589                    errMsg += str(self._getAddress(elt))+"\n"
590                raise XDRtooManyNodesException(errMsg)
591   
592    def _getAddress(self,node):
593        """ This private method constructs the address of a node in the DOM"""
594        parents=list()
595       
596        security=100
597        while (node.nodeName != '#document'):
598            security-=1
599            if security==0:
600                raise Exception("Infinite loop while searching for all the parents ...")
601           
602            parents.insert(0,node.nodeName)
603            node=node.parentNode
604        return parents
605   
606    def addChild(self,nodeName,value,fatherName,*path):
607        """
608        This method adds a child named nodeName to fatherName
609        It also sets attribute "value" to value
610        It returns the createdNode
611        """
612        fatherNode = self._getNode(fatherName,*path)
613        newNode = self._dom.createElement(nodeName)
614       
615        newNode = fatherNode.appendChild(newNode)
616        if value != "":
617            newNode.setAttribute("value", value)
618        return newNode
619   
620    def addMultipleChild(self,value,fatherName,*path):
621        """
622        This methods adds a child to a multiple node to fatherName
623        It also sets attribute "value" to value
624        It returns the createdNode name
625        """
626       
627        # Retrieve next "item" number
628        tagList= []
629        tagList = self._getTags(tagList)
630        itemList=[]
631       
632        for item in tagList:
633            p=re.compile("^item_\d+$")
634            if p.search(item):
635                itemList.append(int(item.split("_")[1]))
636               
637        itemList.sort()
638        try:
639            nextItem = "item_"+str(itemList[-1]+1)
640        except IndexError:
641            nextItem = "item_1"
642
643        self.addChild(nextItem,value,fatherName,*path)
644       
645        return nextItem
646       
647    def nodeExists(self,nodeName,*path):
648        """
649        This method tests if the node exists
650        """
651        try :
652            self._getNode(nodeName,*path)
653        except XDRnoNodeException:
654            return 0
655        else:
656            return 1
657       
658    def tryGetValue(self, default, nodeName, *path):
659        """
660        Search for the node "nodeName" with elements of "path" in its path and return its value
661        If node doesn't exist, use "default" for value
662       
663        It would be cleaner to use "path" as a list, instead of "*path", but this would change all the geValue calls :(
664        To be evaluated later
665        """
666       
667        if not isinstance(default,basestring) :
668            raise XDRillFormed("XDRError : the type of default ", default , "is ", type(default), "instead of a basestring")     
669       
670        try :
671            result = self.getValue(nodeName,*path)
672        except XDRnoNodeException:
673            result = default
674            print "Note : Could not find node \"", nodeName, " \" for path" , path ,". Using default value :", default
675        return result
676
677    def getValue(self,nodeName,*path):
678        """
679        Search for the node "nodeName" with elements of "path" in its path and return its value
680        If node doesn't exist, XDRnoNodeException will be raised
681       
682        It would be cleaner to use "path" as a list, instead of "*path", but this would change all the geValue calls :(
683        To be evaluated later
684        """
685        node = self._getNode(nodeName, *path)
686        return node.getAttribute("value").encode("utf-8")
687
688    def getListValue(self, key, *path):
689        """
690        This procedure gets the asked value from the dataset and returns it as a list
691        """
692        result = self.getValue(key, *path).split(';')
693           
694        return result
695       
696    def setValue(self,value,nodeName,*path):
697        """
698        This method searches for the node "nodeName" with elements of "path" in its path and change its value to "value"
699        If the value is a python list, it's converted into a Tcl list
700        """
701       
702        if isinstance(value,list):
703            value2=[]
704            for elt in value:
705                value2.append(str(elt).strip())
706            value=";".join(value2)
707           
708        try :
709            node=self._getNode(nodeName, *path)
710            node.setAttribute("value",str(value))
711        except :
712            print "Note : Could not find node \"", nodeName, " \" for path" , path ,". skipping setValue"
713           
714       
715    def getChildrenName(self,nodeName,*path):
716        """
717        This method returns a list of the name of all the children of the node named "nodeName".
718        If more than one node has the same name, parts of its path can be specified as for the getValue method
719        """
720        try:
721            node=self._getNode(nodeName, *path)
722        except XDRnoNodeException:
723            return ""
724       
725        #result=list()
726        result=[child.nodeName for child in node.childNodes if child.nodeType == 1]
727            #result.append(child.nodeName)
728           
729        return result
730   
731    def removeNode(self,nodeName,*path):
732        """
733        This method removes the node named "nodeName".
734        If more than one node has the same name, parts of its path can be specified as for the getValue method
735        """
736        node=self._getNode(nodeName,*path)
737        parent = node.parentNode
738        parent.removeChild(node)
739       
740    def save2file(self,fileName):
741        """
742        This method save the dataset in C3Sm XML format
743        """
744        try:
745            f=codecs.open(fileName,"w","utf-8")
746            self._dom.writexml(f,addindent="  ",encoding="utf-8")
747            f.close()
748        except IOError:
749            error("XDRError : could not save XML content to file "+fileName+" from "+os.getcwd()+". Check path, permissions and disk space.")
750
751
752
753 #
754 #                   _ _ ______ _ _           
755 #    /\            (_|_)  ____(_) |         
756 #   /  \   ___  ___ _ _| |__   _| | ___  ___
757 #  / /\ \ / __|/ __| | |  __| | | |/ _ \/ __|
758 # / ____ \\__ \ (__| | | |    | | |  __/\__ \
759 #/_/    \_\___/\___|_|_|_|    |_|_|\___||___/
760 #                                           
761 #                                           
762
763       
764class WriteAsciiFile:
765    """
766    This class allows developers to easily write informations to ASCII files
767    It provides writing methods
768    """
769    def __init__(self,fileName):
770        """
771        This constructor open "fileName"
772        """
773        self._outputFile=open(fileName,"w")
774       
775    def write(self,str):
776        """
777        This method write the string "str" in the file
778        """
779        self._outputFile.write(str)
780    def writeLine(self,line):
781        """
782        This method write the string "str" followed by "\n" in the file
783        """
784        self._outputFile.write(line+"\n")
785       
786    def close(self):
787        self._outputFile.close()
788        del self
789
790
791
792
793       
794class ReadAsciiFile:
795    """ This class provides methods to read and parse ascii files"""
796    def __init__(self,fileName):
797        try:
798            self._inputFile=open(fileName,"r")
799        except IOError:
800            print "XDRError :\nThe file "+fileName+" has not been found\nPlease check that the command supposed to create it is working well\n==============="
801        self._content=self._inputFile.read()
802        self._contentList=self._content.split('\n')
803        self._inputFile.close()
804       
805       
806    def __iter__(self):
807        return self._contentList.__iter__()
808       
809    def getContent(self):
810        """
811        This method returns the content of the file
812        """
813        return self._content
814       
815
816 #
817 # _____                                          _   _                 
818 #|  __ \                                        | | (_)               
819 #| |__) |   _ _ __     ___  _ __   ___ _ __ __ _| |_ _  ___  _ __  ___
820 #|  _  / | | | '_ \   / _ \| '_ \ / _ \ '__/ _` | __| |/ _ \| '_ \/ __|
821 #| | \ \ |_| | | | | | (_) | |_) |  __/ | | (_| | |_| | (_) | | | \__ \
822 #|_|  \_\__,_|_| |_|  \___/| .__/ \___|_|  \__,_|\__|_|\___/|_| |_|___/
823 #                          | |                                         
824 #                          |_|                                             
825 #   
826def getRunsList():
827    """ This function returns a list containing the directories which are considered as runs
828    """
829     # Retrieve list of element in current directory
830    listElt = os.listdir(".")
831    listDir = []
832    for elt in listElt:
833        if os.path.isdir(elt):
834            # The element is a directory
835            p=re.compile('^'+PREFIX+'\d{'+str(DIGIT_NUMBER)+'}$')
836            if p.search(elt):
837                # The directory is detected as a run
838                listDir.append(elt)
839    listDir.sort()           
840    return listDir
841
842def getCurrentRun():
843    """ This function analyses the directories in the current directory and return the name of the directory corresponding to the last "run"
844    """
845   
846    # Retrieve runs list
847    listDir = getRunsList()
848   
849   
850    # Sorting the list to get the last element
851    listDir.sort()
852    if len(listDir) == 0:
853        return createNewRun()
854    return listDir[-1]
855
856def goIntoCurrentRun():
857    """ This function changes directory to go into current run directory, if no run director is present, then it creates RUN001 and goes into it
858    """
859    currentRun = getCurrentRun()
860   
861    if currentRun == "":
862        currentRun = createNewRun()
863       
864    os.chdir(currentRun)
865
866
867def formatRunNumber(int):
868    """ This function formats int to be correct towards the defined format for run number
869    """
870    formatter ="%(#)0"+str(DIGIT_NUMBER)+"d" 
871    return formatter % {"#" : int}
872
873def createNewRun():
874    """ This function creates a new directory following the last detected run.
875        It returns the name of the newly created folder
876    """
877    # Retrieve runs list
878    listDir = getRunsList()
879
880    # Sorting the list to get the last element
881    listDir.sort()
882    if len(listDir) == 0:
883        lastRun = ""
884    else:
885        lastRun = listDir[-1]
886       
887
888    #formatter = '{0:0='+str(DIGIT_NUMBER)+'d}'
889    if lastRun == "" :
890        #nextRunNumber = formatter.format(1)
891        nextRunNumber = formatRunNumber(1)
892    else:
893        p=re.compile('^'+PREFIX+'(\d{'+str(DIGIT_NUMBER)+'})$')
894        m = p.search(lastRun)
895        if m:
896            #nextRunNumber = formatter.format(int(m.group(1))+1)
897            nextRunNumber = formatRunNumber(int(m.group(1))+1)
898        else:
899            print("XDRError : Return from getLastRun function is not well formatted, contact C3Sm team ...")
900       
901    nextRun = PREFIX+nextRunNumber
902    os.mkdir(nextRun)
903    return nextRun
904
905def createNewRunFromLastRun():
906    """ This function creates a new directory following the last detected run and duplicate its content
907        It returns the name of the newly created folder
908    """
909    # Retrieve runs list
910    listDir = getRunsList()
911
912    # Sorting the list to get the last element
913    listDir.sort()
914    if len(listDir) == 0:
915        lastRun = ""
916    else:
917        lastRun = listDir[-1]
918       
919
920    #formatter = '{0:0='+str(DIGIT_NUMBER)+'d}'
921    if lastRun == "" :
922        #nextRunNumber = formatter.format(1)
923        nextRunNumber = formatRunNumber(1)
924        nextRun = PREFIX+nextRunNumber
925        os.mkdir(nextRun)
926    else:
927        p=re.compile('^'+PREFIX+'(\d{'+str(DIGIT_NUMBER)+'})$')
928        m = p.search(lastRun)
929        if m:
930            #nextRunNumber = formatter.format(int(m.group(1))+1)
931            nextRunNumber = formatRunNumber(int(m.group(1))+1)
932            nextRun = PREFIX+nextRunNumber
933            shutil.copytree(lastRun, nextRun)
934        else:
935            print("XDRError : Return from getLastRun function is not well formatted, contact C3Sm team ...")
936       
937   
938    return nextRun
939
940
941
942
943
944
945
946
947def saveDatasetInCurrentRun():
948    """ This function saves the current dataset in the last known run.
949        In order to use this function, you must have initialized the XDR library
950    """
951    if "XDR" not in sys.modules:
952        raise Exception("XDRError : XDR library is not loaded")
953   
954    try :
955        dsout = getDsout()
956    except NameError:
957        dsout = XDR.dsout() 
958   
959    currentRun = getCurrentRun()
960    dsout.save2file(os.path.join(".",currentRun,currentRun+".xml"))
961   
962
963def copyFileInLocalProject(path,tgt_dir="COMMON"):
964    """ This function copy the file path into the common directory.
965    If the file already exists, it compares the two files and rename the new one if they are different
966    It finally returns the new path
967    """
968    global COMMON_DIRECTORY,OrigAppName
969   
970   
971   
972    if tgt_dir == "COMMON" :
973        tgt_dir = COMMON_DIRECTORY
974        ensureDirectory(COMMON_DIRECTORY,clean=False)
975    else :
976        ensureDirectory(tgt_dir,clean=False)
977   
978    tgt_dir = os.path.relpath(tgt_dir,os.getcwd())
979       
980   
981       
982       
983    # Checking if original path exists
984    if not(os.path.exists(path) == True and os.path.isfile(path)):
985        msgerr =  "XDRError : the file "+path+" can't be accessed"
986        error(msgerr)
987   
988    # Checking existence of file in COMMON
989    dirName,fileName = os.path.split(path) 
990   
991   
992    newPath = os.path.join(tgt_dir,fileName)
993   
994   
995    if fileName in os.listdir(tgt_dir):
996        # The file already exists
997        print "This file already exists in "+tgt_dir
998       
999        # Checking equality
1000        if filecmp.cmp(path,newPath):
1001            print "File equal, skipping copy..."
1002           
1003        else:
1004            print "Warning : File differ, previous file will be ecrased (ha ha ha)..."
1005            print "Copying "+path +" in "+newPath
1006            shutil.copy(path,newPath)
1007    else :
1008        print "Copying "+path +" in "+newPath
1009        shutil.copy(path,newPath)
1010    return newPath
1011
1012
1013
1014def copyFileFromDatasetInLocalProject(key,*path):
1015    """ This function retrieves the path from the field identified by key and path (see getValue() )
1016        It copies the file from the retrieved path into the common directory.
1017        If the file already exists, it compares the two files and rename the new one if they are different
1018        The function then update the field defined by key and path
1019    """
1020    originalPath = getValue(key,*path)
1021   
1022    newPath = copyFileInLocalProject(originalPath)
1023   
1024    setValue(newPath,key,*path)
1025    return newPath
1026   
1027def createFileInCurrentRun(fileName,fileContent):
1028    """ This function creates a new file named fileName in current run and writes fileContent into it
1029    """
1030   
1031    currentRun = getCurrentRun()
1032   
1033    if currentRun == "" :
1034        currentRun = createNewRun()
1035   
1036    filePath = os.path.join(".",currentRun,fileName)
1037    f = open(filePath,"w")
1038    f.write(fileContent)
1039    f.close()
1040   
1041    return filePath
1042
1043
1044 #
1045 #_____  _                  _____           
1046 #|  __ \| |                |_   _|         
1047 #| |__) | |_   _  __ _ ______| |  _ __  ___
1048 #|  ___/| | | | |/ _` |______| | | '_ \/ __|
1049 #| |    | | |_| | (_| |     _| |_| | | \__ \
1050 #|_|    |_|\__,_|\__, |    |_____|_| |_|___/
1051 #                 __/ |                     
1052 #                |___/                     
1053
1054
1055
1056class Plugin:
1057    """ All the plugins inherit from this class
1058    """
1059    def __init__(self,type):
1060        """
1061        Initializes the plugin with type = (code|tool)
1062        """
1063        if (type != "code") and (type != "tool"):
1064            error("XDRError : Plugin type was "+type+", it has to be 'code' or 'tool'")
1065        self.type = type
1066        self.infos={}
1067        self.infos['platform']="XDRError : Platform is not specified in current plugin"
1068        self.infos['parallelCommand'] = ""
1069
1070        self.dir2send = []
1071        self.plugin_name = self.__class__.__name__
1072        self.nbcores = 0
1073        self.enable_sav = False
1074       
1075
1076    def get_cores(self):
1077        if self.nbcores == 0 :
1078            msg_err = "Warning : 0 cores reserved for the present computation"
1079            error(msg_err)
1080        return self.nbcores
1081   
1082
1083#    def sendDirectory(self,directory):
1084#        """ This method sends directory on a distant place """
1085#        error("Plugin : sendDirectory() is not implemented in current plugin ...")
1086
1087    def executeDistantCommand(self,command,execDirectory,flags=[]):
1088        """ This method goes into execDirectory and execute command """
1089        error("Plugin : executeDistantCommand() is not implemented in current plugin ...")
1090
1091    def sendDirectory(self,directory):
1092        """ This method adds a directory to the run archive. """
1093        # basename(abspath()) removes the trailing '/'s.
1094        #local_directory = os.path.abspath(directory)
1095        #directory_name = os.path.basename(local_directory)
1096
1097        local_directory = os.path.relpath(directory)
1098
1099        # We don't check that relpath doesn't contain some '../../../'.
1100        # Might be an issue.
1101        # tar removes them on its own, a plain scp might not.
1102
1103        # Also, handling of symlinks is unknown.
1104       
1105        # Check that directory exists
1106        if not os.path.exists(local_directory):
1107            error("Error : " + directory + " doesn't exist")
1108
1109        # Check that we didn't change working directory along the way.
1110        if (len(self.dir2send) > 0):
1111            if os.getcwd() != self._dir2send_curdir:
1112                error("Current directory changed between calls to sendDirectory(). This is not supported !")
1113        else:
1114            self._dir2send_curdir = os.getcwd()
1115
1116        # Add to the list of files to be sent       
1117        self.dir2send.append(local_directory)
1118
1119    def retrieveDirectory(self,directory):
1120        """ This method retrieves directory from the distant place """
1121        error("Plugin : retrieveDirectory is not implemented in current plugin ...")
1122       
1123    def removeDirectory(self,directory):
1124        """ This method removes directory from the distant place """
1125        error("Plugin : removeDirectory is not implemented in current plugin ...")
1126   
1127    def getPlatform(self):
1128        """ This method has to be deleted
1129        """
1130        error("Plugin : getPlatform souldn't be called anymore")
1131       
1132    def getInfos(self):
1133        """ This methods returns informations regarding the plugin as a dictionary.
1134        This dictionary is instantiated in the constructor of mother class Plugin
1135        This method has to be deleted
1136        """
1137        error("Plugin : getInfos souldn't be called anymore")
1138       
1139    def getPluginParam(self,paramName):
1140        """ This method searches for paramName where the plugin is configurated and return its value
1141        """
1142        try:
1143            return getValue(paramName,self.__class__.__name__,self.type+"_plugins")
1144        except XDRtooManyNodesException:
1145            #error("Your plugin "+self.__class__.__name__+" is configurated in multiple places ...\n Remove it from your config !")
1146            return getValue(paramName,self.__class__.__name__,self.type+"_plugins",getValue("name","solver","meta"))
1147
1148    def runSAV(self):
1149        if not self.enable_sav:
1150            print "SAV not available for current plugin"
1151            return
1152
1153        shutil.copy(os.path.join(os.path.dirname(os.path.abspath(__file__)), "SAV.py"), ".")
1154        self.sendDirectory('SAV.py')
1155        self.executeDistantCommand("python SAV.py", ".", "SAV")
1156        self.retrieveDirectory('XDR-FileDB.csv')
1157
1158        db = SAV.FileDB('XDR-FileDB.csv')
1159        print db
1160
1161
1162
1163
1164
1165def loadPlugin(pluginName):
1166   
1167    callDir = os.path.split(scriptDir)[1]
1168    #print callDir
1169    #pluginPath = ""
1170    #if callDir == "XDRpy" :
1171    #    pluginPath = os.path.join(scriptDir,"..","library","DATA","pluginscripts")
1172    #if callDir == "scripts" :
1173    #    pluginPath = os.path.join(scriptDir,"..","..","DATA","pluginscripts")
1174    #   
1175    #if pluginPath == "" :
1176    #    error("Problem, this case is not managed by load plugin")
1177    pluginsPath = getValue("pluginsPath","engine","meta")
1178
1179    print "Loading plugin : "+str(os.path.join(pluginsPath,pluginName+".py"))
1180   
1181 
1182    try:
1183        return imp.load_source(pluginName,os.path.join(pluginsPath,pluginName+".py"))
1184    except IOError:
1185        error("XDRError : plugin \""+pluginName+"\" couldn't be found")
1186
1187
1188
1189def loadCodePlugin(pluginName=""):
1190   
1191    if pluginName == "" :
1192        try:
1193            pluginName = getValue("code_plugins")
1194        except XDRtooManyNodesException:
1195            #error("Your plugin "+self.__class__.__name__+" is configurated in multiple places ...\n Remove it from your config !")
1196            pluginName = getValue("code_plugins",getValue("name","solver","meta"))
1197
1198    pluginLib = loadPlugin(pluginName)
1199    pluginClass = getattr(pluginLib,pluginName)
1200    plugin = pluginClass("code")
1201    return plugin
1202
1203def loadToolPlugin():
1204    try:
1205        pluginName = getValue("tool_plugins","config")
1206    except XDRnoNodeException:
1207        error("XDRError : Your config file is not up to date")
1208       
1209   
1210    pluginLib = loadPlugin(pluginName)
1211    pluginClass = getattr(pluginLib,pluginName)
1212    plugin = pluginClass("tool")
1213    return plugin
1214
1215
1216def executeTool(command,directory):
1217    """ This command execute a tool on a distant service regarding the chosen plugin in config file
1218    """
1219   
1220   
1221    plugin = loadToolPlugin()
1222
1223    plugin.sendDirectory(directory)
1224   
1225    plugin.executeDistantCommand(command,directory)
1226   
1227    plugin.retrieveDirectory(directory)
1228
1229
1230 #           ______                                                              _
1231 #   ____   |  ____|                                                            | |
1232 #  / __ \  | |__  __  _____  ___   ___ ___  _ __ ___  _ __ ___   __ _ _ __   __| |
1233 # / / _` | |  __| \ \/ / _ \/ __| / __/ _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` |
1234 #| | (_| | | |____ >  <  __/ (__ | (_| (_) | | | | | | | | | | | (_| | | | | (_| |
1235 # \ \__,_| |______/_/\_\___|\___| \___\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|
1236 #  \____/                     ______                                             
1237 #                            |______|                                             
1238
1239
1240def exec_command(fun):
1241    """ This function defines the annotation @exec_command, to be used by all plugin scripts.
1242       It defines self.command_exe (defaults to command), self.local_directory (the current directory)
1243       that can then be accessed in executeDistantCommand """
1244    def wrapped_fun(self, command, execDirectory, appli, flags=[]):
1245        print "Plugin : Running executeDistantCommand " + command + " (appli: " + appli + ") in " + execDirectory
1246       
1247        # Initialize some variables
1248        self.command_exe = command
1249        self.local_directory = os.getcwd()
1250
1251        # Used only for testing deployment plugins
1252        if appli == "-c3sm_auto_deployment_tests":
1253            if command == "-c3sm_auto_deploy_test_write-":
1254                self.command_exe = "cat my_input_file > my_new_file"
1255
1256        # Check that execDirectory makes sense
1257        if len(execDirectory) == 0:
1258            print "No execDirectory given. Assuming '.'"
1259            execDirectory = '.'
1260       
1261        if execDirectory[0] == '/' or execDirectory[0] == '~':
1262            error("execDirectory should be relative to the project directory, not an absolute path")
1263
1264        # Run the actual command
1265        r = fun(self, command, execDirectory, appli, flags=[])
1266
1267        # The command is supposed to have uploaded pending files
1268        # Empty the list, so they aren't sent again if we invoke executeDistantCommand another time.
1269        self.dir2send = []
1270
1271        # Make sure we get back to the initial directory
1272        os.chdir(self.local_directory)
1273    return wrapped_fun
1274
1275 #
1276 #            _____                              _           _                    _ _           _   _                 
1277 #   ____    / ____|                            | |         | |                  | (_)         | | (_)               
1278 #  / __ \  | (___  _   _ _ __  _ __   ___  _ __| |_ ___  __| |  __ _ _ __  _ __ | |_  ___ __ _| |_ _  ___  _ __  ___
1279 # / / _` |  \___ \| | | | '_ \| '_ \ / _ \| '__| __/ _ \/ _` | / _` | '_ \| '_ \| | |/ __/ _` | __| |/ _ \| '_ \/ __|
1280 #| | (_| |  ____) | |_| | |_) | |_) | (_) | |  | ||  __/ (_| || (_| | |_) | |_) | | | (_| (_| | |_| | (_) | | | \__ \
1281 # \ \__,_| |_____/ \__,_| .__/| .__/ \___/|_|   \__\___|\__,_| \__,_| .__/| .__/|_|_|\___\__,_|\__|_|\___/|_| |_|___/
1282 #  \____/               | |   | |                          ______   | |   | |                                       
1283 #                       |_|   |_|                         |______|  |_|   |_|                                       
1284
1285def supported_applications(apps):
1286    """ Annotation @supported_applications(['appli1', 'appli2']) automates checking that a passed application is supported """
1287    def wrapper(fun):
1288        def wrapped_fun(self, command, execDirectory, appli, flags=[]):
1289            # This is a list of apps that the user doesn't have to specifically accept.
1290            # XDRpy will handle them internally, and developers of deployment plugins
1291            # don't have to care about them.
1292            apps_whitelist = ['-c3sm_auto_deployment_tests', 'SAV']
1293
1294            if (appli not in apps) and (appli not in apps_whitelist):
1295                error("This application requires the application tag " + appli + ", which is not supported by the plugin " + self.plugin_name)
1296            return fun(self, command, execDirectory, appli, flags=[])
1297        return wrapped_fun
1298    return wrapper
1299
1300def check_command_exe(command_exe):
1301    """ Checks that the command is valid. If it starts with -c3sm_auto-, the associated command hasn't been found """
1302    if command_exe.startswith("-c3sm_auto_"):
1303        error("command was not understood: "+command_exe )
1304
1305   
1306def executeCode(command,currentRunDirectory="None"):
1307   
1308   
1309    error("XDRError : executeCode is not managed anymore in XDR library, update your library")
1310   
1311    try:
1312        pluginName = getValue("code_plugins","config")
1313    except XDRnoNodeException:
1314        error("XDRError : Your config file is not up to date")
1315        return
1316   
1317    if currentRunDirectory=="None" :
1318        currentRunDirectory = getCurrentRun()
1319   
1320    typeRun = "code"
1321   
1322    plugin = loadPlugin(pluginName)
1323   
1324    plugin.sendDirectory(os.path.join(".",COMMON_DIRECTORY),typeRun)
1325   
1326    plugin.sendDirectory(os.path.join(".",getCurrentRun()),typeRun)
1327   
1328    plugin.executeDistantCommand(command,currentRunDirectory,typeRun)
1329   
1330def retrieveCodeDirectory(directory):
1331    try:
1332        pluginName = getValue("code_plugins","config")
1333    except XDRnoNodeException:
1334        print "XDRError : Your config file is not up to date"
1335        return
1336   
1337    plugin = loadPlugin(pluginName)
1338   
1339    plugin.retrieveDirectory(directory,"code")
1340   
1341   
1342   
1343
1344 #
1345 #
1346 # ______                    _   _                 
1347 #|  ____|                  | | (_)               
1348 #| |__  __  _____ ___ _ __ | |_ _  ___  _ __  ___
1349 #|  __| \ \/ / __/ _ \ '_ \| __| |/ _ \| '_ \/ __|
1350 #| |____ >  < (_|  __/ |_) | |_| | (_) | | | \__ \
1351 #|______/_/\_\___\___| .__/ \__|_|\___/|_| |_|___/
1352 #                    | |                         
1353 #                    |_|                         
1354 #
1355
1356class XDRException(Exception):
1357    """ All exceptions raisen by XDR library inherits from this one"""
1358   
1359class XDRnoNodeException(XDRException):
1360    """" No node found """
1361
1362class XDRtooManyNodesException(XDRException):
1363    """ Too many nodes have been found"""
1364       
1365class XDRnoFileException(XDRException):
1366    """ No file found """
1367
1368class XDRillFormed(XDRException):
1369    """ Ill formed XML address """
1370
1371
1372
1373
1374def replace_pattern_in_file(file,searchExp,replaceExp):
1375    """ serach and replace a pattern in a file
1376    needs the fileinput package"""
1377   
1378    if not os.path.exists(file) :
1379        print "Warning : file not found:"+file
1380        return
1381   
1382    replace = 0
1383    for line in fileinput.input(file, inplace=1):
1384        if searchExp in line:
1385            line = line.replace(searchExp,replaceExp)
1386            replace += 1
1387        sys.stdout.write(line)
1388       
1389    if replace == 0 :
1390        print "Warning : no replacement made \n "+file+":"+ searchExp +">"+replaceExp
1391    else :
1392        print str(replace)+" replacement made \n"+file+":"+ searchExp +">"+replaceExp
1393    return
1394       
1395 #       
1396 # ______                               _                _   _                 
1397 #|  ____|                             | |              | | (_)               
1398 #| |__ _ __ ___  __ _ _   _  ___ _ __ | |_    __ _  ___| |_ _  ___  _ __  ___
1399 #|  __| '__/ _ \/ _` | | | |/ _ \ '_ \| __|  / _` |/ __| __| |/ _ \| '_ \/ __|
1400 #| |  | | |  __/ (_| | |_| |  __/ | | | |_  | (_| | (__| |_| | (_) | | | \__ \
1401 #|_|  |_|  \___|\__, |\__,_|\___|_| |_|\__|  \__,_|\___|\__|_|\___/|_| |_|___/
1402 #                  | |                                                       
1403 #                  |_|                                                       
1404
1405   
1406def afterstring(text,pattern):
1407    """
1408    This procedure searches for the first line beginning with "pattern" in "text" and return the rest of the line
1409    """
1410    p= re.compile('^[ \t]*'+pattern+'[\t ]*(.*?)[ \t]*$', re.MULTILINE)
1411    m=p.search(text)
1412    if m:
1413        return m.group(1)
1414    else:
1415        print "No result found for "+pattern+" ..."
1416        return "Error"
1417   
1418
1419def grep(text,pattern):
1420    textLines=text.split("\n")
1421    p= re.compile(pattern)
1422    result=[]
1423    for line in textLines:
1424        m=p.search(line)
1425        if m:
1426            result.append(line)
1427    return "\n".join(result)
1428   
1429   
1430def betweenlines(text,pattern1,pattern2):
1431    """
1432    This procedure return the text between the lines "pattern1" and "pattern2"
1433    """
1434    textLines=text.split("\n")
1435    p=re.compile('^[ \t]*'+pattern1+'[ \t]*$')
1436    position="out"
1437    result=[]
1438    for line in textLines:
1439        m=p.search(line)
1440        if m:
1441            if position=="out":
1442                p=re.compile('^[ \t]*'+pattern2+'[ \t]*$')
1443                position="in"
1444            else:
1445                position="out"
1446        else:
1447            if position=="in":
1448                result.append(line)
1449    return "\n".join(result)
1450
1451
1452def getColumn(text,pos,sep=None):
1453    """ This procedure reads the lines of "text" and return an array containing the pos-th element of each line
1454    sep is the separator, if not specified, the separator is assumed to be any kind of whitespace (tab, space, etc ...)
1455    """
1456    finalList = []
1457    result=text.split("\n")
1458    for line in result:
1459        toto=line.split(sep)
1460        if len(toto)>=pos:
1461            finalList.append(toto[pos-1].strip())
1462    return finalList
1463
1464   
1465def readFile(filename):
1466    """ This procedure returns the content of the file "filename" """
1467#    asciiIn = ReadAsciiFile(filename)
1468#    result = asciiIn.getContent()
1469    return ReadAsciiFile(filename).getContent()
1470   
1471   
1472
1473
1474def pairwise(iterable):
1475    """
1476    This procedure allows to loop in a list in a pairwise fashion
1477    need package izip
1478    s -> (s0,s1), (s2,s3), (s4, s5), ...
1479    """
1480    a = iter(iterable)
1481    return izip(a, a)
1482       
1483def ensureDirectory(list_strings,clean=False):
1484    """ Check wether a directory exists in the current working directory
1485    argument is a list of strings to be contcatenated.
1486    Returns the directory path in absolute form
1487    """
1488   
1489    if isinstance(list_strings, basestring) :
1490        dirlist = [list_strings]
1491    else :
1492        dirlist = list_strings
1493   
1494       
1495    directory= os.path.join(os.getcwd(),*dirlist)
1496 
1497   
1498    if os.path.exists(directory) :
1499        if clean :
1500            print "Ensure clean directory", directory
1501            # directory exists, and need to clean it
1502            shutil.rmtree(directory)
1503            os.makedirs(directory)
1504        else :
1505            # directory exists, and no need to clean it
1506            pass
1507           
1508    else :
1509        #directory does not exists
1510        print "Create directory", directory
1511        os.makedirs(directory)
1512   
1513   
1514   
1515    return directory
1516
1517def readAsciiBound(asciiBoundFile):
1518    asciiBound = readFile(asciiBoundFile)
1519    asciiBound = asciiBound.split("\n")
1520   
1521    nbPatches = int(asciiBound[1].strip().split(" ")[0])
1522
1523    results= []
1524    for i,line in enumerate(asciiBound):
1525        if re.compile("^\s*Patch: ").search(line):
1526            results.append(asciiBound[i+1].strip())
1527
1528    if len(results) != nbPatches:
1529        msg = "Mismatch between the number of patches and the patches read in file "+asciiBoundFile
1530        error(msg)
1531
1532    return results
1533
1534
1535def getFileList(path,filter_search="",output="listonly"):
1536    """ return the list of files in a path (compulsory) matching a filter string (facultative).
1537    output (facultative) can be : - listonly : a list of the files
1538                                  - relative : a list relative pathes
1539                                  - absolute : a list of absolute path
1540    """
1541   
1542   
1543    lresult =  []
1544    glob_arg = os.path.join(path,filter_search)
1545    list_dir = glob.glob(glob_arg)
1546   
1547   
1548    if output == "relative" :
1549        for f in list_dir:
1550                lresult.append(os.path.relpath(f))
1551    if output == "listonly" :
1552         for f in list_dir:
1553                lresult.append(os.path.relpath(f,path))
1554    if output == "absolute" :
1555        lresult = list_dir
1556
1557    #print "getFileList",lresult
1558   
1559   
1560    return sorted(lresult)
1561
1562
1563
1564 #
1565 # _____  __  __         _   _ _     
1566 #|  __ \|  \/  |       | | (_) |   
1567 #| |__) | \  / |  _   _| |_ _| |___
1568 #|  ___/| |\/| | | | | | __| | / __|
1569 #| |    | |  | | | |_| | |_| | \__ \
1570 #|_|    |_|  |_|  \__,_|\__|_|_|___/
1571 #                                   
1572                                   
1573def SimToColor(simu) :
1574    color = "black"
1575    if simu == "1" :
1576        color="black"
1577    if simu == "2" :
1578        color="red"
1579    if simu == "3" :
1580        color="blue"
1581    if simu == "4" :
1582        color="green4"   
1583    return color
1584
1585def SimToSymbol(simu) :
1586    symbol = ""
1587    if simu == "1" :
1588        symbol="circle"
1589    if simu == "2" :
1590        symbol="square"
1591    if simu == "3" :
1592        symbol="triangle"
1593    if simu == "4" :
1594        symbol="diamond"
1595    return symbol
1596
Note: See TracBrowser for help on using the repository browser.